D-Bus  1.5.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_mutex_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_mutex_lock ((connection)->slot_mutex);        \
00077   } while (0)
00078 
00079 #define SLOTS_UNLOCK(connection) do {                   \
00080     _dbus_mutex_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 
00209 typedef struct DBusMessageFilter DBusMessageFilter;
00210 
00214 struct DBusMessageFilter
00215 {
00216   DBusAtomic refcount; 
00217   DBusHandleMessageFunction function; 
00218   void *user_data; 
00219   DBusFreeFunction free_user_data_function; 
00220 };
00221 
00222 
00226 struct DBusPreallocatedSend
00227 {
00228   DBusConnection *connection; 
00229   DBusList *queue_link;       
00230   DBusList *counter_link;     
00231 };
00232 
00233 #if HAVE_DECL_MSG_NOSIGNAL
00234 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00235 #else
00236 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00237 #endif
00238 
00242 struct DBusConnection
00243 {
00244   DBusAtomic refcount; 
00246   DBusMutex *mutex; 
00248   DBusMutex *dispatch_mutex;     
00249   DBusCondVar *dispatch_cond;    
00250   DBusMutex *io_path_mutex;      
00251   DBusCondVar *io_path_cond;     
00253   DBusList *outgoing_messages; 
00254   DBusList *incoming_messages; 
00255   DBusList *expired_messages;  
00257   DBusMessage *message_borrowed; 
00261   int n_outgoing;              
00262   int n_incoming;              
00264   DBusCounter *outgoing_counter; 
00266   DBusTransport *transport;    
00267   DBusWatchList *watches;      
00268   DBusTimeoutList *timeouts;   
00270   DBusList *filter_list;        
00272   DBusMutex *slot_mutex;        
00273   DBusDataSlotList slot_list;   
00275   DBusHashTable *pending_replies;  
00277   dbus_uint32_t client_serial;       
00278   DBusList *disconnect_message_link; 
00280   DBusWakeupMainFunction wakeup_main_function; 
00281   void *wakeup_main_data; 
00282   DBusFreeFunction free_wakeup_main_data; 
00284   DBusDispatchStatusFunction dispatch_status_function; 
00285   void *dispatch_status_data; 
00286   DBusFreeFunction free_dispatch_status_data; 
00288   DBusDispatchStatus last_dispatch_status; 
00290   DBusObjectTree *objects; 
00292   char *server_guid; 
00294   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00295    * from connection->mutex and all bitfields in a word have to be read/written together.
00296    * So you can't have a different lock for different bitfields in the same word.
00297    */
00298   dbus_bool_t dispatch_acquired; 
00299   dbus_bool_t io_path_acquired;  
00301   unsigned int shareable : 1; 
00303   unsigned int exit_on_disconnect : 1; 
00305   unsigned int route_peer_messages : 1; 
00307   unsigned int disconnected_message_arrived : 1;   
00311   unsigned int disconnected_message_processed : 1; 
00315 #ifndef DBUS_DISABLE_CHECKS
00316   unsigned int have_connection_lock : 1; 
00317 #endif
00318   
00319 #ifndef DBUS_DISABLE_CHECKS
00320   int generation; 
00321 #endif 
00322 };
00323 
00324 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00325 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00326                                                                               DBusDispatchStatus  new_status);
00327 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00328 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00329 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00330 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00331 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00332 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00333 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
00334                                                                               dbus_uint32_t       client_serial);
00335 
00336 static DBusMessageFilter *
00337 _dbus_message_filter_ref (DBusMessageFilter *filter)
00338 {
00339 #ifdef DBUS_DISABLE_ASSERT
00340   _dbus_atomic_inc (&filter->refcount);
00341 #else
00342   dbus_int32_t old_value;
00343 
00344   old_value = _dbus_atomic_inc (&filter->refcount);
00345   _dbus_assert (old_value > 0);
00346 #endif
00347 
00348   return filter;
00349 }
00350 
00351 static void
00352 _dbus_message_filter_unref (DBusMessageFilter *filter)
00353 {
00354   dbus_int32_t old_value;
00355 
00356   old_value = _dbus_atomic_dec (&filter->refcount);
00357   _dbus_assert (old_value > 0);
00358 
00359   if (old_value == 1)
00360     {
00361       if (filter->free_user_data_function)
00362         (* filter->free_user_data_function) (filter->user_data);
00363       
00364       dbus_free (filter);
00365     }
00366 }
00367 
00373 void
00374 _dbus_connection_lock (DBusConnection *connection)
00375 {
00376   CONNECTION_LOCK (connection);
00377 }
00378 
00384 void
00385 _dbus_connection_unlock (DBusConnection *connection)
00386 {
00387   DBusList *expired_messages;
00388   DBusList *iter;
00389 
00390   if (TRACE_LOCKS)
00391     {
00392       _dbus_verbose ("UNLOCK\n");
00393     }
00394 
00395   /* If we had messages that expired (fell off the incoming or outgoing
00396    * queues) while we were locked, actually release them now */
00397   expired_messages = connection->expired_messages;
00398   connection->expired_messages = NULL;
00399 
00400   RELEASING_LOCK_CHECK (connection);
00401   _dbus_mutex_unlock (connection->mutex);
00402 
00403   for (iter = _dbus_list_pop_first_link (&expired_messages);
00404       iter != NULL;
00405       iter = _dbus_list_pop_first_link (&expired_messages))
00406     {
00407       DBusMessage *message = iter->data;
00408 
00409       dbus_message_unref (message);
00410       _dbus_list_free_link (iter);
00411     }
00412 }
00413 
00421 static void
00422 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00423 {
00424   if (connection->wakeup_main_function)
00425     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00426 }
00427 
00428 #ifdef DBUS_BUILD_TESTS
00429 /* For now this function isn't used */
00439 dbus_bool_t
00440 _dbus_connection_queue_received_message (DBusConnection *connection,
00441                                          DBusMessage    *message)
00442 {
00443   DBusList *link;
00444 
00445   link = _dbus_list_alloc_link (message);
00446   if (link == NULL)
00447     return FALSE;
00448 
00449   dbus_message_ref (message);
00450   _dbus_connection_queue_received_message_link (connection, link);
00451 
00452   return TRUE;
00453 }
00454 
00467 void 
00468 _dbus_connection_test_get_locks (DBusConnection *connection,
00469                                  DBusMutex     **mutex_loc,
00470                                  DBusMutex     **dispatch_mutex_loc,
00471                                  DBusMutex     **io_path_mutex_loc,
00472                                  DBusCondVar   **dispatch_cond_loc,
00473                                  DBusCondVar   **io_path_cond_loc)
00474 {
00475   *mutex_loc = connection->mutex;
00476   *dispatch_mutex_loc = connection->dispatch_mutex;
00477   *io_path_mutex_loc = connection->io_path_mutex; 
00478   *dispatch_cond_loc = connection->dispatch_cond;
00479   *io_path_cond_loc = connection->io_path_cond;
00480 }
00481 #endif
00482 
00491 void
00492 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00493                                               DBusList        *link)
00494 {
00495   DBusPendingCall *pending;
00496   dbus_uint32_t reply_serial;
00497   DBusMessage *message;
00498   
00499   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00500   
00501   _dbus_list_append_link (&connection->incoming_messages,
00502                           link);
00503   message = link->data;
00504 
00505   /* If this is a reply we're waiting on, remove timeout for it */
00506   reply_serial = dbus_message_get_reply_serial (message);
00507   if (reply_serial != 0)
00508     {
00509       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00510                                              reply_serial);
00511       if (pending != NULL)
00512         {
00513           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00514             _dbus_connection_remove_timeout_unlocked (connection,
00515                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00516 
00517           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00518         }
00519     }
00520   
00521   
00522 
00523   connection->n_incoming += 1;
00524 
00525   _dbus_connection_wakeup_mainloop (connection);
00526   
00527   _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00528                  message,
00529                  dbus_message_type_to_string (dbus_message_get_type (message)),
00530                  dbus_message_get_path (message) ?
00531                  dbus_message_get_path (message) :
00532                  "no path",
00533                  dbus_message_get_interface (message) ?
00534                  dbus_message_get_interface (message) :
00535                  "no interface",
00536                  dbus_message_get_member (message) ?
00537                  dbus_message_get_member (message) :
00538                  "no member",
00539                  dbus_message_get_signature (message),
00540                  dbus_message_get_reply_serial (message),
00541                  connection,
00542                  connection->n_incoming);}
00543 
00552 void
00553 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00554                                                  DBusList *link)
00555 {
00556   HAVE_LOCK_CHECK (connection);
00557   
00558   _dbus_list_append_link (&connection->incoming_messages, link);
00559 
00560   connection->n_incoming += 1;
00561 
00562   _dbus_connection_wakeup_mainloop (connection);
00563   
00564   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00565                  link->data, connection, connection->n_incoming);
00566 }
00567 
00568 
00576 dbus_bool_t
00577 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00578 {
00579   HAVE_LOCK_CHECK (connection);
00580   return connection->outgoing_messages != NULL;
00581 }
00582 
00592 dbus_bool_t
00593 dbus_connection_has_messages_to_send (DBusConnection *connection)
00594 {
00595   dbus_bool_t v;
00596   
00597   _dbus_return_val_if_fail (connection != NULL, FALSE);
00598 
00599   CONNECTION_LOCK (connection);
00600   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00601   CONNECTION_UNLOCK (connection);
00602 
00603   return v;
00604 }
00605 
00613 DBusMessage*
00614 _dbus_connection_get_message_to_send (DBusConnection *connection)
00615 {
00616   HAVE_LOCK_CHECK (connection);
00617   
00618   return _dbus_list_get_last (&connection->outgoing_messages);
00619 }
00620 
00629 void
00630 _dbus_connection_message_sent_unlocked (DBusConnection *connection,
00631                                         DBusMessage    *message)
00632 {
00633   DBusList *link;
00634 
00635   HAVE_LOCK_CHECK (connection);
00636   
00637   /* This can be called before we even complete authentication, since
00638    * it's called on disconnect to clean up the outgoing queue.
00639    * It's also called as we successfully send each message.
00640    */
00641   
00642   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00643   _dbus_assert (link != NULL);
00644   _dbus_assert (link->data == message);
00645 
00646   _dbus_list_unlink (&connection->outgoing_messages,
00647                      link);
00648   _dbus_list_prepend_link (&connection->expired_messages, link);
00649 
00650   connection->n_outgoing -= 1;
00651 
00652   _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00653                  message,
00654                  dbus_message_type_to_string (dbus_message_get_type (message)),
00655                  dbus_message_get_path (message) ?
00656                  dbus_message_get_path (message) :
00657                  "no path",
00658                  dbus_message_get_interface (message) ?
00659                  dbus_message_get_interface (message) :
00660                  "no interface",
00661                  dbus_message_get_member (message) ?
00662                  dbus_message_get_member (message) :
00663                  "no member",
00664                  dbus_message_get_signature (message),
00665                  connection, connection->n_outgoing);
00666 
00667   /* It's OK that in principle we call the notify function, because for the
00668    * outgoing limit, there isn't one */
00669   _dbus_message_remove_counter (message, connection->outgoing_counter);
00670 
00671   /* The message will actually be unreffed when we unlock */
00672 }
00673 
00675 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00676                                                   DBusWatch     *watch);
00678 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00679                                                   DBusWatch     *watch);
00681 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00682                                                   DBusWatch     *watch,
00683                                                   dbus_bool_t    enabled);
00684 
00685 static dbus_bool_t
00686 protected_change_watch (DBusConnection         *connection,
00687                         DBusWatch              *watch,
00688                         DBusWatchAddFunction    add_function,
00689                         DBusWatchRemoveFunction remove_function,
00690                         DBusWatchToggleFunction toggle_function,
00691                         dbus_bool_t             enabled)
00692 {
00693   dbus_bool_t retval;
00694 
00695   HAVE_LOCK_CHECK (connection);
00696 
00697   /* The original purpose of protected_change_watch() was to hold a
00698    * ref on the connection while dropping the connection lock, then
00699    * calling out to the app.  This was a broken hack that did not
00700    * work, since the connection was in a hosed state (no WatchList
00701    * field) while calling out.
00702    *
00703    * So for now we'll just keep the lock while calling out. This means
00704    * apps are not allowed to call DBusConnection methods inside a
00705    * watch function or they will deadlock.
00706    *
00707    * The "real fix" is to use the _and_unlock() pattern found
00708    * elsewhere in the code, to defer calling out to the app until
00709    * we're about to drop locks and return flow of control to the app
00710    * anyway.
00711    *
00712    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00713    */
00714 
00715   if (connection->watches)
00716     {
00717       if (add_function)
00718         retval = (* add_function) (connection->watches, watch);
00719       else if (remove_function)
00720         {
00721           retval = TRUE;
00722           (* remove_function) (connection->watches, watch);
00723         }
00724       else
00725         {
00726           retval = TRUE;
00727           (* toggle_function) (connection->watches, watch, enabled);
00728         }
00729       return retval;
00730     }
00731   else
00732     return FALSE;
00733 }
00734      
00735 
00747 dbus_bool_t
00748 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00749                                      DBusWatch      *watch)
00750 {
00751   return protected_change_watch (connection, watch,
00752                                  _dbus_watch_list_add_watch,
00753                                  NULL, NULL, FALSE);
00754 }
00755 
00765 void
00766 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00767                                         DBusWatch      *watch)
00768 {
00769   protected_change_watch (connection, watch,
00770                           NULL,
00771                           _dbus_watch_list_remove_watch,
00772                           NULL, FALSE);
00773 }
00774 
00785 void
00786 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00787                                         DBusWatch      *watch,
00788                                         dbus_bool_t     enabled)
00789 {
00790   _dbus_assert (watch != NULL);
00791 
00792   protected_change_watch (connection, watch,
00793                           NULL, NULL,
00794                           _dbus_watch_list_toggle_watch,
00795                           enabled);
00796 }
00797 
00799 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00800                                                    DBusTimeout     *timeout);
00802 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00803                                                    DBusTimeout     *timeout);
00805 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00806                                                    DBusTimeout     *timeout,
00807                                                    dbus_bool_t      enabled);
00808 
00809 static dbus_bool_t
00810 protected_change_timeout (DBusConnection           *connection,
00811                           DBusTimeout              *timeout,
00812                           DBusTimeoutAddFunction    add_function,
00813                           DBusTimeoutRemoveFunction remove_function,
00814                           DBusTimeoutToggleFunction toggle_function,
00815                           dbus_bool_t               enabled)
00816 {
00817   dbus_bool_t retval;
00818 
00819   HAVE_LOCK_CHECK (connection);
00820 
00821   /* The original purpose of protected_change_timeout() was to hold a
00822    * ref on the connection while dropping the connection lock, then
00823    * calling out to the app.  This was a broken hack that did not
00824    * work, since the connection was in a hosed state (no TimeoutList
00825    * field) while calling out.
00826    *
00827    * So for now we'll just keep the lock while calling out. This means
00828    * apps are not allowed to call DBusConnection methods inside a
00829    * timeout function or they will deadlock.
00830    *
00831    * The "real fix" is to use the _and_unlock() pattern found
00832    * elsewhere in the code, to defer calling out to the app until
00833    * we're about to drop locks and return flow of control to the app
00834    * anyway.
00835    *
00836    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00837    */
00838 
00839   if (connection->timeouts)
00840     {
00841       if (add_function)
00842         retval = (* add_function) (connection->timeouts, timeout);
00843       else if (remove_function)
00844         {
00845           retval = TRUE;
00846           (* remove_function) (connection->timeouts, timeout);
00847         }
00848       else
00849         {
00850           retval = TRUE;
00851           (* toggle_function) (connection->timeouts, timeout, enabled);
00852         }
00853       return retval;
00854     }
00855   else
00856     return FALSE;
00857 }
00858 
00871 dbus_bool_t
00872 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00873                                        DBusTimeout    *timeout)
00874 {
00875   return protected_change_timeout (connection, timeout,
00876                                    _dbus_timeout_list_add_timeout,
00877                                    NULL, NULL, FALSE);
00878 }
00879 
00889 void
00890 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00891                                           DBusTimeout    *timeout)
00892 {
00893   protected_change_timeout (connection, timeout,
00894                             NULL,
00895                             _dbus_timeout_list_remove_timeout,
00896                             NULL, FALSE);
00897 }
00898 
00909 void
00910 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00911                                           DBusTimeout      *timeout,
00912                                           dbus_bool_t       enabled)
00913 {
00914   protected_change_timeout (connection, timeout,
00915                             NULL, NULL,
00916                             _dbus_timeout_list_toggle_timeout,
00917                             enabled);
00918 }
00919 
00920 static dbus_bool_t
00921 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00922                                                DBusPendingCall *pending)
00923 {
00924   dbus_uint32_t reply_serial;
00925   DBusTimeout *timeout;
00926 
00927   HAVE_LOCK_CHECK (connection);
00928 
00929   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00930 
00931   _dbus_assert (reply_serial != 0);
00932 
00933   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00934 
00935   if (timeout)
00936     {
00937       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00938         return FALSE;
00939       
00940       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00941                                         reply_serial,
00942                                         pending))
00943         {
00944           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00945 
00946           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00947           HAVE_LOCK_CHECK (connection);
00948           return FALSE;
00949         }
00950       
00951       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00952     }
00953   else
00954     {
00955       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00956                                         reply_serial,
00957                                         pending))
00958         {
00959           HAVE_LOCK_CHECK (connection);
00960           return FALSE;
00961         }
00962     }
00963 
00964   _dbus_pending_call_ref_unlocked (pending);
00965 
00966   HAVE_LOCK_CHECK (connection);
00967   
00968   return TRUE;
00969 }
00970 
00971 static void
00972 free_pending_call_on_hash_removal (void *data)
00973 {
00974   DBusPendingCall *pending;
00975   DBusConnection  *connection;
00976   
00977   if (data == NULL)
00978     return;
00979 
00980   pending = data;
00981 
00982   connection = _dbus_pending_call_get_connection_unlocked (pending);
00983 
00984   HAVE_LOCK_CHECK (connection);
00985   
00986   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00987     {
00988       _dbus_connection_remove_timeout_unlocked (connection,
00989                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00990       
00991       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00992     }
00993 
00994   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00995    * here, but the pending call finalizer could in principle call out to 
00996    * application code so we pretty much have to... some larger code reorg 
00997    * might be needed.
00998    */
00999   _dbus_connection_ref_unlocked (connection);
01000   _dbus_pending_call_unref_and_unlock (pending);
01001   CONNECTION_LOCK (connection);
01002   _dbus_connection_unref_unlocked (connection);
01003 }
01004 
01005 static void
01006 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
01007                                                DBusPendingCall *pending)
01008 {
01009   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
01010    * say the least.
01011    */
01012   _dbus_hash_table_remove_int (connection->pending_replies,
01013                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01014 }
01015 
01016 static void
01017 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
01018                                                  DBusPendingCall *pending)
01019 {
01020   /* The idea here is to avoid finalizing the pending call
01021    * with the lock held, since there's a destroy notifier
01022    * in pending call that goes out to application code.
01023    *
01024    * There's an extra unlock inside the hash table
01025    * "free pending call" function FIXME...
01026    */
01027   _dbus_pending_call_ref_unlocked (pending);
01028   _dbus_hash_table_remove_int (connection->pending_replies,
01029                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01030 
01031   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01032       _dbus_connection_remove_timeout_unlocked (connection,
01033               _dbus_pending_call_get_timeout_unlocked (pending));
01034 
01035   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01036 
01037   _dbus_pending_call_unref_and_unlock (pending);
01038 }
01039 
01048 void
01049 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01050                                       DBusPendingCall *pending)
01051 {
01052   CONNECTION_LOCK (connection);
01053   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01054 }
01055 
01065 static dbus_bool_t
01066 _dbus_connection_acquire_io_path (DBusConnection *connection,
01067                                   int             timeout_milliseconds)
01068 {
01069   dbus_bool_t we_acquired;
01070   
01071   HAVE_LOCK_CHECK (connection);
01072 
01073   /* We don't want the connection to vanish */
01074   _dbus_connection_ref_unlocked (connection);
01075 
01076   /* We will only touch io_path_acquired which is protected by our mutex */
01077   CONNECTION_UNLOCK (connection);
01078   
01079   _dbus_verbose ("locking io_path_mutex\n");
01080   _dbus_mutex_lock (connection->io_path_mutex);
01081 
01082   _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01083                  connection->io_path_acquired, timeout_milliseconds);
01084 
01085   we_acquired = FALSE;
01086   
01087   if (connection->io_path_acquired)
01088     {
01089       if (timeout_milliseconds != -1)
01090         {
01091           _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01092                          timeout_milliseconds);
01093 
01094           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01095                                            connection->io_path_mutex,
01096                                            timeout_milliseconds))
01097             {
01098               /* We timed out before anyone signaled. */
01099               /* (writing the loop to handle the !timedout case by
01100                * waiting longer if needed is a pain since dbus
01101                * wraps pthread_cond_timedwait to take a relative
01102                * time instead of absolute, something kind of stupid
01103                * on our part. for now it doesn't matter, we will just
01104                * end up back here eventually.)
01105                */
01106             }
01107         }
01108       else
01109         {
01110           while (connection->io_path_acquired)
01111             {
01112               _dbus_verbose ("waiting for IO path to be acquirable\n");
01113               _dbus_condvar_wait (connection->io_path_cond, 
01114                                   connection->io_path_mutex);
01115             }
01116         }
01117     }
01118   
01119   if (!connection->io_path_acquired)
01120     {
01121       we_acquired = TRUE;
01122       connection->io_path_acquired = TRUE;
01123     }
01124   
01125   _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01126                  connection->io_path_acquired, we_acquired);
01127 
01128   _dbus_verbose ("unlocking io_path_mutex\n");
01129   _dbus_mutex_unlock (connection->io_path_mutex);
01130 
01131   CONNECTION_LOCK (connection);
01132   
01133   HAVE_LOCK_CHECK (connection);
01134 
01135   _dbus_connection_unref_unlocked (connection);
01136   
01137   return we_acquired;
01138 }
01139 
01147 static void
01148 _dbus_connection_release_io_path (DBusConnection *connection)
01149 {
01150   HAVE_LOCK_CHECK (connection);
01151   
01152   _dbus_verbose ("locking io_path_mutex\n");
01153   _dbus_mutex_lock (connection->io_path_mutex);
01154   
01155   _dbus_assert (connection->io_path_acquired);
01156 
01157   _dbus_verbose ("start connection->io_path_acquired = %d\n",
01158                  connection->io_path_acquired);
01159   
01160   connection->io_path_acquired = FALSE;
01161   _dbus_condvar_wake_one (connection->io_path_cond);
01162 
01163   _dbus_verbose ("unlocking io_path_mutex\n");
01164   _dbus_mutex_unlock (connection->io_path_mutex);
01165 }
01166 
01202 void
01203 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01204                                         DBusPendingCall *pending,
01205                                         unsigned int    flags,
01206                                         int             timeout_milliseconds)
01207 {
01208   _dbus_verbose ("start\n");
01209   
01210   HAVE_LOCK_CHECK (connection);
01211   
01212   if (connection->n_outgoing == 0)
01213     flags &= ~DBUS_ITERATION_DO_WRITING;
01214 
01215   if (_dbus_connection_acquire_io_path (connection,
01216                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01217     {
01218       HAVE_LOCK_CHECK (connection);
01219       
01220       if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01221         {
01222           _dbus_verbose ("pending call completed while acquiring I/O path");
01223         }
01224       else if ( (pending != NULL) &&
01225                 _dbus_connection_peek_for_reply_unlocked (connection,
01226                                                           _dbus_pending_call_get_reply_serial_unlocked (pending)))
01227         {
01228           _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01229         }
01230       else
01231         {
01232           _dbus_transport_do_iteration (connection->transport,
01233                                         flags, timeout_milliseconds);
01234         }
01235 
01236       _dbus_connection_release_io_path (connection);
01237     }
01238 
01239   HAVE_LOCK_CHECK (connection);
01240 
01241   _dbus_verbose ("end\n");
01242 }
01243 
01253 DBusConnection*
01254 _dbus_connection_new_for_transport (DBusTransport *transport)
01255 {
01256   DBusConnection *connection;
01257   DBusWatchList *watch_list;
01258   DBusTimeoutList *timeout_list;
01259   DBusHashTable *pending_replies;
01260   DBusList *disconnect_link;
01261   DBusMessage *disconnect_message;
01262   DBusCounter *outgoing_counter;
01263   DBusObjectTree *objects;
01264   
01265   watch_list = NULL;
01266   connection = NULL;
01267   pending_replies = NULL;
01268   timeout_list = NULL;
01269   disconnect_link = NULL;
01270   disconnect_message = NULL;
01271   outgoing_counter = NULL;
01272   objects = NULL;
01273   
01274   watch_list = _dbus_watch_list_new ();
01275   if (watch_list == NULL)
01276     goto error;
01277 
01278   timeout_list = _dbus_timeout_list_new ();
01279   if (timeout_list == NULL)
01280     goto error;  
01281 
01282   pending_replies =
01283     _dbus_hash_table_new (DBUS_HASH_INT,
01284                           NULL,
01285                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01286   if (pending_replies == NULL)
01287     goto error;
01288   
01289   connection = dbus_new0 (DBusConnection, 1);
01290   if (connection == NULL)
01291     goto error;
01292 
01293   _dbus_mutex_new_at_location (&connection->mutex);
01294   if (connection->mutex == NULL)
01295     goto error;
01296 
01297   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01298   if (connection->io_path_mutex == NULL)
01299     goto error;
01300 
01301   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01302   if (connection->dispatch_mutex == NULL)
01303     goto error;
01304   
01305   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01306   if (connection->dispatch_cond == NULL)
01307     goto error;
01308   
01309   _dbus_condvar_new_at_location (&connection->io_path_cond);
01310   if (connection->io_path_cond == NULL)
01311     goto error;
01312 
01313   _dbus_mutex_new_at_location (&connection->slot_mutex);
01314   if (connection->slot_mutex == NULL)
01315     goto error;
01316 
01317   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01318                                                 DBUS_INTERFACE_LOCAL,
01319                                                 "Disconnected");
01320   
01321   if (disconnect_message == NULL)
01322     goto error;
01323 
01324   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01325   if (disconnect_link == NULL)
01326     goto error;
01327 
01328   outgoing_counter = _dbus_counter_new ();
01329   if (outgoing_counter == NULL)
01330     goto error;
01331 
01332   objects = _dbus_object_tree_new (connection);
01333   if (objects == NULL)
01334     goto error;
01335   
01336   if (_dbus_modify_sigpipe)
01337     _dbus_disable_sigpipe ();
01338 
01339   /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
01340   _dbus_atomic_inc (&connection->refcount);
01341   connection->transport = transport;
01342   connection->watches = watch_list;
01343   connection->timeouts = timeout_list;
01344   connection->pending_replies = pending_replies;
01345   connection->outgoing_counter = outgoing_counter;
01346   connection->filter_list = NULL;
01347   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01348   connection->objects = objects;
01349   connection->exit_on_disconnect = FALSE;
01350   connection->shareable = FALSE;
01351   connection->route_peer_messages = FALSE;
01352   connection->disconnected_message_arrived = FALSE;
01353   connection->disconnected_message_processed = FALSE;
01354   
01355 #ifndef DBUS_DISABLE_CHECKS
01356   connection->generation = _dbus_current_generation;
01357 #endif
01358   
01359   _dbus_data_slot_list_init (&connection->slot_list);
01360 
01361   connection->client_serial = 1;
01362 
01363   connection->disconnect_message_link = disconnect_link;
01364 
01365   CONNECTION_LOCK (connection);
01366   
01367   if (!_dbus_transport_set_connection (transport, connection))
01368     {
01369       CONNECTION_UNLOCK (connection);
01370 
01371       goto error;
01372     }
01373 
01374   _dbus_transport_ref (transport);
01375 
01376   CONNECTION_UNLOCK (connection);
01377   
01378   return connection;
01379   
01380  error:
01381   if (disconnect_message != NULL)
01382     dbus_message_unref (disconnect_message);
01383   
01384   if (disconnect_link != NULL)
01385     _dbus_list_free_link (disconnect_link);
01386   
01387   if (connection != NULL)
01388     {
01389       _dbus_condvar_free_at_location (&connection->io_path_cond);
01390       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01391       _dbus_mutex_free_at_location (&connection->mutex);
01392       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01393       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01394       _dbus_mutex_free_at_location (&connection->slot_mutex);
01395       dbus_free (connection);
01396     }
01397   if (pending_replies)
01398     _dbus_hash_table_unref (pending_replies);
01399   
01400   if (watch_list)
01401     _dbus_watch_list_free (watch_list);
01402 
01403   if (timeout_list)
01404     _dbus_timeout_list_free (timeout_list);
01405 
01406   if (outgoing_counter)
01407     _dbus_counter_unref (outgoing_counter);
01408 
01409   if (objects)
01410     _dbus_object_tree_unref (objects);
01411   
01412   return NULL;
01413 }
01414 
01422 DBusConnection *
01423 _dbus_connection_ref_unlocked (DBusConnection *connection)
01424 {  
01425   _dbus_assert (connection != NULL);
01426   _dbus_assert (connection->generation == _dbus_current_generation);
01427 
01428   HAVE_LOCK_CHECK (connection);
01429 
01430   _dbus_atomic_inc (&connection->refcount);
01431 
01432   return connection;
01433 }
01434 
01441 void
01442 _dbus_connection_unref_unlocked (DBusConnection *connection)
01443 {
01444   dbus_bool_t last_unref;
01445 
01446   HAVE_LOCK_CHECK (connection);
01447   
01448   _dbus_assert (connection != NULL);
01449 
01450   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01451 
01452   if (last_unref)
01453     _dbus_connection_last_unref (connection);
01454 }
01455 
01456 static dbus_uint32_t
01457 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01458 {
01459   dbus_uint32_t serial;
01460 
01461   serial = connection->client_serial++;
01462 
01463   if (connection->client_serial == 0)
01464     connection->client_serial = 1;
01465 
01466   return serial;
01467 }
01468 
01482 dbus_bool_t
01483 _dbus_connection_handle_watch (DBusWatch                   *watch,
01484                                unsigned int                 condition,
01485                                void                        *data)
01486 {
01487   DBusConnection *connection;
01488   dbus_bool_t retval;
01489   DBusDispatchStatus status;
01490 
01491   connection = data;
01492 
01493   _dbus_verbose ("start\n");
01494   
01495   CONNECTION_LOCK (connection);
01496 
01497   if (!_dbus_connection_acquire_io_path (connection, 1))
01498     {
01499       /* another thread is handling the message */
01500       CONNECTION_UNLOCK (connection);
01501       return TRUE;
01502     }
01503 
01504   HAVE_LOCK_CHECK (connection);
01505   retval = _dbus_transport_handle_watch (connection->transport,
01506                                          watch, condition);
01507 
01508   _dbus_connection_release_io_path (connection);
01509 
01510   HAVE_LOCK_CHECK (connection);
01511 
01512   _dbus_verbose ("middle\n");
01513   
01514   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01515 
01516   /* this calls out to user code */
01517   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01518 
01519   _dbus_verbose ("end\n");
01520   
01521   return retval;
01522 }
01523 
01524 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01525 static DBusHashTable *shared_connections = NULL;
01526 static DBusList *shared_connections_no_guid = NULL;
01527 
01528 static void
01529 close_connection_on_shutdown (DBusConnection *connection)
01530 {
01531   DBusMessage *message;
01532 
01533   dbus_connection_ref (connection);
01534   _dbus_connection_close_possibly_shared (connection);
01535 
01536   /* Churn through to the Disconnected message */
01537   while ((message = dbus_connection_pop_message (connection)))
01538     {
01539       dbus_message_unref (message);
01540     }
01541   dbus_connection_unref (connection);
01542 }
01543 
01544 static void
01545 shared_connections_shutdown (void *data)
01546 {
01547   int n_entries;
01548   
01549   _DBUS_LOCK (shared_connections);
01550   
01551   /* This is a little bit unpleasant... better ideas? */
01552   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01553     {
01554       DBusConnection *connection;
01555       DBusHashIter iter;
01556       
01557       _dbus_hash_iter_init (shared_connections, &iter);
01558       _dbus_hash_iter_next (&iter);
01559        
01560       connection = _dbus_hash_iter_get_value (&iter);
01561 
01562       _DBUS_UNLOCK (shared_connections);
01563       close_connection_on_shutdown (connection);
01564       _DBUS_LOCK (shared_connections);
01565 
01566       /* The connection should now be dead and not in our hash ... */
01567       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01568     }
01569 
01570   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01571   
01572   _dbus_hash_table_unref (shared_connections);
01573   shared_connections = NULL;
01574 
01575   if (shared_connections_no_guid != NULL)
01576     {
01577       DBusConnection *connection;
01578       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01579       while (connection != NULL)
01580         {
01581           _DBUS_UNLOCK (shared_connections);
01582           close_connection_on_shutdown (connection);
01583           _DBUS_LOCK (shared_connections);
01584           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01585         }
01586     }
01587 
01588   shared_connections_no_guid = NULL;
01589   
01590   _DBUS_UNLOCK (shared_connections);
01591 }
01592 
01593 static dbus_bool_t
01594 connection_lookup_shared (DBusAddressEntry  *entry,
01595                           DBusConnection   **result)
01596 {
01597   _dbus_verbose ("checking for existing connection\n");
01598   
01599   *result = NULL;
01600   
01601   _DBUS_LOCK (shared_connections);
01602 
01603   if (shared_connections == NULL)
01604     {
01605       _dbus_verbose ("creating shared_connections hash table\n");
01606       
01607       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01608                                                  dbus_free,
01609                                                  NULL);
01610       if (shared_connections == NULL)
01611         {
01612           _DBUS_UNLOCK (shared_connections);
01613           return FALSE;
01614         }
01615 
01616       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01617         {
01618           _dbus_hash_table_unref (shared_connections);
01619           shared_connections = NULL;
01620           _DBUS_UNLOCK (shared_connections);
01621           return FALSE;
01622         }
01623 
01624       _dbus_verbose ("  successfully created shared_connections\n");
01625       
01626       _DBUS_UNLOCK (shared_connections);
01627       return TRUE; /* no point looking up in the hash we just made */
01628     }
01629   else
01630     {
01631       const char *guid;
01632 
01633       guid = dbus_address_entry_get_value (entry, "guid");
01634       
01635       if (guid != NULL)
01636         {
01637           DBusConnection *connection;
01638           
01639           connection = _dbus_hash_table_lookup_string (shared_connections,
01640                                                        guid);
01641 
01642           if (connection)
01643             {
01644               /* The DBusConnection can't be finalized without taking
01645                * the shared_connections lock to remove it from the
01646                * hash.  So it's safe to ref the connection here.
01647                * However, it may be disconnected if the Disconnected
01648                * message hasn't been processed yet, in which case we
01649                * want to pretend it isn't in the hash and avoid
01650                * returning it.
01651                *
01652                * The idea is to avoid ever returning a disconnected connection
01653                * from dbus_connection_open(). We could just synchronously
01654                * drop our shared ref to the connection on connection disconnect,
01655                * and then assert here that the connection is connected, but
01656                * that causes reentrancy headaches.
01657                */
01658               CONNECTION_LOCK (connection);
01659               if (_dbus_connection_get_is_connected_unlocked (connection))
01660                 {
01661                   _dbus_connection_ref_unlocked (connection);
01662                   *result = connection;
01663                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01664                                  guid);
01665                 }
01666               else
01667                 {
01668                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01669                                  guid);
01670                 }
01671               CONNECTION_UNLOCK (connection);
01672             }
01673         }
01674       
01675       _DBUS_UNLOCK (shared_connections);
01676       return TRUE;
01677     }
01678 }
01679 
01680 static dbus_bool_t
01681 connection_record_shared_unlocked (DBusConnection *connection,
01682                                    const char     *guid)
01683 {
01684   char *guid_key;
01685   char *guid_in_connection;
01686 
01687   HAVE_LOCK_CHECK (connection);
01688   _dbus_assert (connection->server_guid == NULL);
01689   _dbus_assert (connection->shareable);
01690 
01691   /* get a hard ref on this connection, even if
01692    * we won't in fact store it in the hash, we still
01693    * need to hold a ref on it until it's disconnected.
01694    */
01695   _dbus_connection_ref_unlocked (connection);
01696 
01697   if (guid == NULL)
01698     {
01699       _DBUS_LOCK (shared_connections);
01700 
01701       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01702         {
01703           _DBUS_UNLOCK (shared_connections);
01704           return FALSE;
01705         }
01706 
01707       _DBUS_UNLOCK (shared_connections);
01708       return TRUE; /* don't store in the hash */
01709     }
01710   
01711   /* A separate copy of the key is required in the hash table, because
01712    * we don't have a lock on the connection when we are doing a hash
01713    * lookup.
01714    */
01715   
01716   guid_key = _dbus_strdup (guid);
01717   if (guid_key == NULL)
01718     return FALSE;
01719 
01720   guid_in_connection = _dbus_strdup (guid);
01721   if (guid_in_connection == NULL)
01722     {
01723       dbus_free (guid_key);
01724       return FALSE;
01725     }
01726   
01727   _DBUS_LOCK (shared_connections);
01728   _dbus_assert (shared_connections != NULL);
01729   
01730   if (!_dbus_hash_table_insert_string (shared_connections,
01731                                        guid_key, connection))
01732     {
01733       dbus_free (guid_key);
01734       dbus_free (guid_in_connection);
01735       _DBUS_UNLOCK (shared_connections);
01736       return FALSE;
01737     }
01738 
01739   connection->server_guid = guid_in_connection;
01740 
01741   _dbus_verbose ("stored connection to %s to be shared\n",
01742                  connection->server_guid);
01743   
01744   _DBUS_UNLOCK (shared_connections);
01745 
01746   _dbus_assert (connection->server_guid != NULL);
01747   
01748   return TRUE;
01749 }
01750 
01751 static void
01752 connection_forget_shared_unlocked (DBusConnection *connection)
01753 {
01754   HAVE_LOCK_CHECK (connection);
01755 
01756   if (!connection->shareable)
01757     return;
01758   
01759   _DBUS_LOCK (shared_connections);
01760       
01761   if (connection->server_guid != NULL)
01762     {
01763       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01764                      connection->server_guid);
01765       
01766       if (!_dbus_hash_table_remove_string (shared_connections,
01767                                            connection->server_guid))
01768         _dbus_assert_not_reached ("connection was not in the shared table");
01769       
01770       dbus_free (connection->server_guid);
01771       connection->server_guid = NULL;
01772     }
01773   else
01774     {
01775       _dbus_list_remove (&shared_connections_no_guid, connection);
01776     }
01777 
01778   _DBUS_UNLOCK (shared_connections);
01779   
01780   /* remove our reference held on all shareable connections */
01781   _dbus_connection_unref_unlocked (connection);
01782 }
01783 
01784 static DBusConnection*
01785 connection_try_from_address_entry (DBusAddressEntry *entry,
01786                                    DBusError        *error)
01787 {
01788   DBusTransport *transport;
01789   DBusConnection *connection;
01790 
01791   transport = _dbus_transport_open (entry, error);
01792 
01793   if (transport == NULL)
01794     {
01795       _DBUS_ASSERT_ERROR_IS_SET (error);
01796       return NULL;
01797     }
01798 
01799   connection = _dbus_connection_new_for_transport (transport);
01800 
01801   _dbus_transport_unref (transport);
01802   
01803   if (connection == NULL)
01804     {
01805       _DBUS_SET_OOM (error);
01806       return NULL;
01807     }
01808 
01809 #ifndef DBUS_DISABLE_CHECKS
01810   _dbus_assert (!connection->have_connection_lock);
01811 #endif
01812   return connection;
01813 }
01814 
01815 /*
01816  * If the shared parameter is true, then any existing connection will
01817  * be used (and if a new connection is created, it will be available
01818  * for use by others). If the shared parameter is false, a new
01819  * connection will always be created, and the new connection will
01820  * never be returned to other callers.
01821  *
01822  * @param address the address
01823  * @param shared whether the connection is shared or private
01824  * @param error error return
01825  * @returns the connection or #NULL on error
01826  */
01827 static DBusConnection*
01828 _dbus_connection_open_internal (const char     *address,
01829                                 dbus_bool_t     shared,
01830                                 DBusError      *error)
01831 {
01832   DBusConnection *connection;
01833   DBusAddressEntry **entries;
01834   DBusError tmp_error = DBUS_ERROR_INIT;
01835   DBusError first_error = DBUS_ERROR_INIT;
01836   int len, i;
01837 
01838   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01839 
01840   _dbus_verbose ("opening %s connection to: %s\n",
01841                  shared ? "shared" : "private", address);
01842   
01843   if (!dbus_parse_address (address, &entries, &len, error))
01844     return NULL;
01845 
01846   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01847   
01848   connection = NULL;
01849 
01850   for (i = 0; i < len; i++)
01851     {
01852       if (shared)
01853         {
01854           if (!connection_lookup_shared (entries[i], &connection))
01855             _DBUS_SET_OOM (&tmp_error);
01856         }
01857 
01858       if (connection == NULL)
01859         {
01860           connection = connection_try_from_address_entry (entries[i],
01861                                                           &tmp_error);
01862 
01863           if (connection != NULL && shared)
01864             {
01865               const char *guid;
01866                   
01867               connection->shareable = TRUE;
01868                   
01869               /* guid may be NULL */
01870               guid = dbus_address_entry_get_value (entries[i], "guid");
01871                   
01872               CONNECTION_LOCK (connection);
01873           
01874               if (!connection_record_shared_unlocked (connection, guid))
01875                 {
01876                   _DBUS_SET_OOM (&tmp_error);
01877                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01878                   dbus_connection_unref (connection);
01879                   connection = NULL;
01880                 }
01881               else
01882                 CONNECTION_UNLOCK (connection);
01883             }
01884         }
01885       
01886       if (connection)
01887         break;
01888 
01889       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01890       
01891       if (i == 0)
01892         dbus_move_error (&tmp_error, &first_error);
01893       else
01894         dbus_error_free (&tmp_error);
01895     }
01896   
01897   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01898   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01899   
01900   if (connection == NULL)
01901     {
01902       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01903       dbus_move_error (&first_error, error);
01904     }
01905   else
01906     dbus_error_free (&first_error);
01907   
01908   dbus_address_entries_free (entries);
01909   return connection;
01910 }
01911 
01920 void
01921 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01922 {
01923   _dbus_assert (connection != NULL);
01924   _dbus_assert (connection->generation == _dbus_current_generation);
01925 
01926   CONNECTION_LOCK (connection);
01927   _dbus_connection_close_possibly_shared_and_unlock (connection);
01928 }
01929 
01930 static DBusPreallocatedSend*
01931 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01932 {
01933   DBusPreallocatedSend *preallocated;
01934 
01935   HAVE_LOCK_CHECK (connection);
01936   
01937   _dbus_assert (connection != NULL);
01938   
01939   preallocated = dbus_new (DBusPreallocatedSend, 1);
01940   if (preallocated == NULL)
01941     return NULL;
01942 
01943   preallocated->queue_link = _dbus_list_alloc_link (NULL);
01944   if (preallocated->queue_link == NULL)
01945     goto failed_0;
01946 
01947   preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01948   if (preallocated->counter_link == NULL)
01949     goto failed_1;
01950 
01951   _dbus_counter_ref (preallocated->counter_link->data);
01952 
01953   preallocated->connection = connection;
01954   
01955   return preallocated;
01956   
01957  failed_1:
01958   _dbus_list_free_link (preallocated->queue_link);
01959  failed_0:
01960   dbus_free (preallocated);
01961   
01962   return NULL;
01963 }
01964 
01965 /* Called with lock held, does not update dispatch status */
01966 static void
01967 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01968                                                        DBusPreallocatedSend *preallocated,
01969                                                        DBusMessage          *message,
01970                                                        dbus_uint32_t        *client_serial)
01971 {
01972   dbus_uint32_t serial;
01973 
01974   preallocated->queue_link->data = message;
01975   _dbus_list_prepend_link (&connection->outgoing_messages,
01976                            preallocated->queue_link);
01977 
01978   /* It's OK that we'll never call the notify function, because for the
01979    * outgoing limit, there isn't one */
01980   _dbus_message_add_counter_link (message,
01981                                   preallocated->counter_link);
01982 
01983   dbus_free (preallocated);
01984   preallocated = NULL;
01985   
01986   dbus_message_ref (message);
01987   
01988   connection->n_outgoing += 1;
01989 
01990   _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01991                  message,
01992                  dbus_message_type_to_string (dbus_message_get_type (message)),
01993                  dbus_message_get_path (message) ?
01994                  dbus_message_get_path (message) :
01995                  "no path",
01996                  dbus_message_get_interface (message) ?
01997                  dbus_message_get_interface (message) :
01998                  "no interface",
01999                  dbus_message_get_member (message) ?
02000                  dbus_message_get_member (message) :
02001                  "no member",
02002                  dbus_message_get_signature (message),
02003                  dbus_message_get_destination (message) ?
02004                  dbus_message_get_destination (message) :
02005                  "null",
02006                  connection,
02007                  connection->n_outgoing);
02008 
02009   if (dbus_message_get_serial (message) == 0)
02010     {
02011       serial = _dbus_connection_get_next_client_serial (connection);
02012       dbus_message_set_serial (message, serial);
02013       if (client_serial)
02014         *client_serial = serial;
02015     }
02016   else
02017     {
02018       if (client_serial)
02019         *client_serial = dbus_message_get_serial (message);
02020     }
02021 
02022   _dbus_verbose ("Message %p serial is %u\n",
02023                  message, dbus_message_get_serial (message));
02024   
02025   dbus_message_lock (message);
02026 
02027   /* Now we need to run an iteration to hopefully just write the messages
02028    * out immediately, and otherwise get them queued up
02029    */
02030   _dbus_connection_do_iteration_unlocked (connection,
02031                                           NULL,
02032                                           DBUS_ITERATION_DO_WRITING,
02033                                           -1);
02034 
02035   /* If stuff is still queued up, be sure we wake up the main loop */
02036   if (connection->n_outgoing > 0)
02037     _dbus_connection_wakeup_mainloop (connection);
02038 }
02039 
02040 static void
02041 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02042                                                DBusPreallocatedSend *preallocated,
02043                                                DBusMessage          *message,
02044                                                dbus_uint32_t        *client_serial)
02045 {
02046   DBusDispatchStatus status;
02047 
02048   HAVE_LOCK_CHECK (connection);
02049   
02050   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02051                                                          preallocated,
02052                                                          message, client_serial);
02053 
02054   _dbus_verbose ("middle\n");
02055   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02056 
02057   /* this calls out to user code */
02058   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02059 }
02060 
02070 dbus_bool_t
02071 _dbus_connection_send_and_unlock (DBusConnection *connection,
02072                                   DBusMessage    *message,
02073                                   dbus_uint32_t  *client_serial)
02074 {
02075   DBusPreallocatedSend *preallocated;
02076 
02077   _dbus_assert (connection != NULL);
02078   _dbus_assert (message != NULL);
02079   
02080   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02081   if (preallocated == NULL)
02082     {
02083       CONNECTION_UNLOCK (connection);
02084       return FALSE;
02085     }
02086 
02087   _dbus_connection_send_preallocated_and_unlock (connection,
02088                                                  preallocated,
02089                                                  message,
02090                                                  client_serial);
02091   return TRUE;
02092 }
02093 
02118 void
02119 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02120 {
02121   dbus_int32_t refcount;
02122 
02123   CONNECTION_LOCK (connection);
02124 
02125   refcount = _dbus_atomic_get (&connection->refcount);
02126   /* The caller should have at least one ref */
02127   _dbus_assert (refcount >= 1);
02128 
02129   if (refcount == 1)
02130     _dbus_connection_close_possibly_shared_and_unlock (connection);
02131   else
02132     CONNECTION_UNLOCK (connection);
02133 }
02134 
02135 
02145 static void
02146 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02147 {
02148   if (timeout_milliseconds == -1)
02149     _dbus_sleep_milliseconds (1000);
02150   else if (timeout_milliseconds < 100)
02151     ; /* just busy loop */
02152   else if (timeout_milliseconds <= 1000)
02153     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02154   else
02155     _dbus_sleep_milliseconds (1000);
02156 }
02157 
02158 static DBusMessage *
02159 generate_local_error_message (dbus_uint32_t serial, 
02160                               char *error_name, 
02161                               char *error_msg)
02162 {
02163   DBusMessage *message;
02164   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02165   if (!message)
02166     goto out;
02167 
02168   if (!dbus_message_set_error_name (message, error_name))
02169     {
02170       dbus_message_unref (message);
02171       message = NULL;
02172       goto out; 
02173     }
02174 
02175   dbus_message_set_no_reply (message, TRUE); 
02176 
02177   if (!dbus_message_set_reply_serial (message,
02178                                       serial))
02179     {
02180       dbus_message_unref (message);
02181       message = NULL;
02182       goto out;
02183     }
02184 
02185   if (error_msg != NULL)
02186     {
02187       DBusMessageIter iter;
02188 
02189       dbus_message_iter_init_append (message, &iter);
02190       if (!dbus_message_iter_append_basic (&iter,
02191                                            DBUS_TYPE_STRING,
02192                                            &error_msg))
02193         {
02194           dbus_message_unref (message);
02195           message = NULL;
02196           goto out;
02197         }
02198     }
02199 
02200  out:
02201   return message;
02202 }
02203 
02204 /*
02205  * Peek the incoming queue to see if we got reply for a specific serial
02206  */
02207 static dbus_bool_t
02208 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02209                                           dbus_uint32_t   client_serial)
02210 {
02211   DBusList *link;
02212   HAVE_LOCK_CHECK (connection);
02213 
02214   link = _dbus_list_get_first_link (&connection->incoming_messages);
02215 
02216   while (link != NULL)
02217     {
02218       DBusMessage *reply = link->data;
02219 
02220       if (dbus_message_get_reply_serial (reply) == client_serial)
02221         {
02222           _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02223           return TRUE;
02224         }
02225       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02226     }
02227 
02228   return FALSE;
02229 }
02230 
02231 /* This is slightly strange since we can pop a message here without
02232  * the dispatch lock.
02233  */
02234 static DBusMessage*
02235 check_for_reply_unlocked (DBusConnection *connection,
02236                           dbus_uint32_t   client_serial)
02237 {
02238   DBusList *link;
02239 
02240   HAVE_LOCK_CHECK (connection);
02241   
02242   link = _dbus_list_get_first_link (&connection->incoming_messages);
02243 
02244   while (link != NULL)
02245     {
02246       DBusMessage *reply = link->data;
02247 
02248       if (dbus_message_get_reply_serial (reply) == client_serial)
02249         {
02250           _dbus_list_remove_link (&connection->incoming_messages, link);
02251           connection->n_incoming  -= 1;
02252           return reply;
02253         }
02254       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02255     }
02256 
02257   return NULL;
02258 }
02259 
02260 static void
02261 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02262 {
02263    /* We can't iterate over the hash in the normal way since we'll be
02264     * dropping the lock for each item. So we restart the
02265     * iter each time as we drain the hash table.
02266     */
02267    
02268    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02269     {
02270       DBusPendingCall *pending;
02271       DBusHashIter iter;
02272       
02273       _dbus_hash_iter_init (connection->pending_replies, &iter);
02274       _dbus_hash_iter_next (&iter);
02275        
02276       pending = _dbus_hash_iter_get_value (&iter);
02277       _dbus_pending_call_ref_unlocked (pending);
02278        
02279       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02280                                                        connection);
02281 
02282       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02283           _dbus_connection_remove_timeout_unlocked (connection,
02284                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02285       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02286       _dbus_hash_iter_remove_entry (&iter);
02287 
02288       _dbus_pending_call_unref_and_unlock (pending);
02289       CONNECTION_LOCK (connection);
02290     }
02291   HAVE_LOCK_CHECK (connection);
02292 }
02293 
02294 static void
02295 complete_pending_call_and_unlock (DBusConnection  *connection,
02296                                   DBusPendingCall *pending,
02297                                   DBusMessage     *message)
02298 {
02299   _dbus_pending_call_set_reply_unlocked (pending, message);
02300   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02301   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02302  
02303   /* Must be called unlocked since it invokes app callback */
02304   _dbus_pending_call_complete (pending);
02305   dbus_pending_call_unref (pending);
02306 }
02307 
02308 static dbus_bool_t
02309 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02310                                               DBusPendingCall *pending)
02311 {
02312   DBusMessage *reply;
02313   DBusDispatchStatus status;
02314 
02315   reply = check_for_reply_unlocked (connection, 
02316                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02317   if (reply != NULL)
02318     {
02319       _dbus_verbose ("checked for reply\n");
02320 
02321       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02322 
02323       complete_pending_call_and_unlock (connection, pending, reply);
02324       dbus_message_unref (reply);
02325 
02326       CONNECTION_LOCK (connection);
02327       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02328       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02329       dbus_pending_call_unref (pending);
02330 
02331       return TRUE;
02332     }
02333 
02334   return FALSE;
02335 }
02336 
02351 void
02352 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02353 {
02354   long start_tv_sec, start_tv_usec;
02355   long tv_sec, tv_usec;
02356   DBusDispatchStatus status;
02357   DBusConnection *connection;
02358   dbus_uint32_t client_serial;
02359   DBusTimeout *timeout;
02360   int timeout_milliseconds, elapsed_milliseconds;
02361 
02362   _dbus_assert (pending != NULL);
02363 
02364   if (dbus_pending_call_get_completed (pending))
02365     return;
02366 
02367   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02368 
02369   connection = _dbus_pending_call_get_connection_and_lock (pending);
02370   
02371   /* Flush message queue - note, can affect dispatch status */
02372   _dbus_connection_flush_unlocked (connection);
02373 
02374   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02375 
02376   /* note that timeout_milliseconds is limited to a smallish value
02377    * in _dbus_pending_call_new() so overflows aren't possible
02378    * below
02379    */
02380   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02381   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02382   if (timeout)
02383     {
02384       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02385 
02386       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02387                      timeout_milliseconds,
02388                      client_serial,
02389                      start_tv_sec, start_tv_usec);
02390     }
02391   else
02392     {
02393       timeout_milliseconds = -1;
02394 
02395       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02396     }
02397 
02398   /* check to see if we already got the data off the socket */
02399   /* from another blocked pending call */
02400   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02401     return;
02402 
02403   /* Now we wait... */
02404   /* always block at least once as we know we don't have the reply yet */
02405   _dbus_connection_do_iteration_unlocked (connection,
02406                                           pending,
02407                                           DBUS_ITERATION_DO_READING |
02408                                           DBUS_ITERATION_BLOCK,
02409                                           timeout_milliseconds);
02410 
02411  recheck_status:
02412 
02413   _dbus_verbose ("top of recheck\n");
02414   
02415   HAVE_LOCK_CHECK (connection);
02416   
02417   /* queue messages and get status */
02418 
02419   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02420 
02421   /* the get_completed() is in case a dispatch() while we were blocking
02422    * got the reply instead of us.
02423    */
02424   if (_dbus_pending_call_get_completed_unlocked (pending))
02425     {
02426       _dbus_verbose ("Pending call completed by dispatch\n");
02427       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02428       dbus_pending_call_unref (pending);
02429       return;
02430     }
02431   
02432   if (status == DBUS_DISPATCH_DATA_REMAINS)
02433     {
02434       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02435         return;
02436     }
02437   
02438   _dbus_get_current_time (&tv_sec, &tv_usec);
02439   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02440           (tv_usec - start_tv_usec) / 1000;
02441   
02442   if (!_dbus_connection_get_is_connected_unlocked (connection))
02443     {
02444       DBusMessage *error_msg;
02445 
02446       error_msg = generate_local_error_message (client_serial,
02447                                                 DBUS_ERROR_DISCONNECTED, 
02448                                                 "Connection was disconnected before a reply was received"); 
02449 
02450       /* on OOM error_msg is set to NULL */
02451       complete_pending_call_and_unlock (connection, pending, error_msg);
02452       dbus_pending_call_unref (pending);
02453       return;
02454     }
02455   else if (connection->disconnect_message_link == NULL)
02456     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02457   else if (timeout == NULL)
02458     {
02459        if (status == DBUS_DISPATCH_NEED_MEMORY)
02460         {
02461           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02462            * we may already have a reply in the buffer and just can't process
02463            * it.
02464            */
02465           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02466 
02467           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02468         }
02469       else
02470         {          
02471           /* block again, we don't have the reply buffered yet. */
02472           _dbus_connection_do_iteration_unlocked (connection,
02473                                                   pending,
02474                                                   DBUS_ITERATION_DO_READING |
02475                                                   DBUS_ITERATION_BLOCK,
02476                                                   timeout_milliseconds - elapsed_milliseconds);
02477         }
02478 
02479       goto recheck_status;
02480     }
02481   else if (tv_sec < start_tv_sec)
02482     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02483   else if (elapsed_milliseconds < timeout_milliseconds)
02484     {
02485       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02486       
02487       if (status == DBUS_DISPATCH_NEED_MEMORY)
02488         {
02489           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02490            * we may already have a reply in the buffer and just can't process
02491            * it.
02492            */
02493           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02494 
02495           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02496         }
02497       else
02498         {          
02499           /* block again, we don't have the reply buffered yet. */
02500           _dbus_connection_do_iteration_unlocked (connection,
02501                                                   NULL,
02502                                                   DBUS_ITERATION_DO_READING |
02503                                                   DBUS_ITERATION_BLOCK,
02504                                                   timeout_milliseconds - elapsed_milliseconds);
02505         }
02506 
02507       goto recheck_status;
02508     }
02509 
02510   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02511                  elapsed_milliseconds);
02512 
02513   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02514   
02515   /* unlock and call user code */
02516   complete_pending_call_and_unlock (connection, pending, NULL);
02517 
02518   /* update user code on dispatch status */
02519   CONNECTION_LOCK (connection);
02520   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02521   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02522   dbus_pending_call_unref (pending);
02523 }
02524 
02561 DBusConnection*
02562 dbus_connection_open (const char     *address,
02563                       DBusError      *error)
02564 {
02565   DBusConnection *connection;
02566 
02567   _dbus_return_val_if_fail (address != NULL, NULL);
02568   _dbus_return_val_if_error_is_set (error, NULL);
02569 
02570   connection = _dbus_connection_open_internal (address,
02571                                                TRUE,
02572                                                error);
02573 
02574   return connection;
02575 }
02576 
02604 DBusConnection*
02605 dbus_connection_open_private (const char     *address,
02606                               DBusError      *error)
02607 {
02608   DBusConnection *connection;
02609 
02610   _dbus_return_val_if_fail (address != NULL, NULL);
02611   _dbus_return_val_if_error_is_set (error, NULL);
02612 
02613   connection = _dbus_connection_open_internal (address,
02614                                                FALSE,
02615                                                error);
02616 
02617   return connection;
02618 }
02619 
02626 DBusConnection *
02627 dbus_connection_ref (DBusConnection *connection)
02628 {
02629   _dbus_return_val_if_fail (connection != NULL, NULL);
02630   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02631 
02632   _dbus_atomic_inc (&connection->refcount);
02633 
02634   return connection;
02635 }
02636 
02637 static void
02638 free_outgoing_message (void *element,
02639                        void *data)
02640 {
02641   DBusMessage *message = element;
02642   DBusConnection *connection = data;
02643 
02644   _dbus_message_remove_counter (message, connection->outgoing_counter);
02645   dbus_message_unref (message);
02646 }
02647 
02648 /* This is run without the mutex held, but after the last reference
02649  * to the connection has been dropped we should have no thread-related
02650  * problems
02651  */
02652 static void
02653 _dbus_connection_last_unref (DBusConnection *connection)
02654 {
02655   DBusList *link;
02656 
02657   _dbus_verbose ("Finalizing connection %p\n", connection);
02658 
02659   _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02660 
02661   /* You have to disconnect the connection before unref:ing it. Otherwise
02662    * you won't get the disconnected message.
02663    */
02664   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02665   _dbus_assert (connection->server_guid == NULL);
02666   
02667   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02668   _dbus_object_tree_free_all_unlocked (connection->objects);
02669   
02670   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02671   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02672   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02673   
02674   _dbus_watch_list_free (connection->watches);
02675   connection->watches = NULL;
02676   
02677   _dbus_timeout_list_free (connection->timeouts);
02678   connection->timeouts = NULL;
02679 
02680   _dbus_data_slot_list_free (&connection->slot_list);
02681   
02682   link = _dbus_list_get_first_link (&connection->filter_list);
02683   while (link != NULL)
02684     {
02685       DBusMessageFilter *filter = link->data;
02686       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02687 
02688       filter->function = NULL;
02689       _dbus_message_filter_unref (filter); /* calls app callback */
02690       link->data = NULL;
02691       
02692       link = next;
02693     }
02694   _dbus_list_clear (&connection->filter_list);
02695   
02696   /* ---- Done with stuff that invokes application callbacks */
02697 
02698   _dbus_object_tree_unref (connection->objects);  
02699 
02700   _dbus_hash_table_unref (connection->pending_replies);
02701   connection->pending_replies = NULL;
02702   
02703   _dbus_list_clear (&connection->filter_list);
02704   
02705   _dbus_list_foreach (&connection->outgoing_messages,
02706                       free_outgoing_message,
02707                       connection);
02708   _dbus_list_clear (&connection->outgoing_messages);
02709   
02710   _dbus_list_foreach (&connection->incoming_messages,
02711                       (DBusForeachFunction) dbus_message_unref,
02712                       NULL);
02713   _dbus_list_clear (&connection->incoming_messages);
02714 
02715   _dbus_counter_unref (connection->outgoing_counter);
02716 
02717   _dbus_transport_unref (connection->transport);
02718 
02719   if (connection->disconnect_message_link)
02720     {
02721       DBusMessage *message = connection->disconnect_message_link->data;
02722       dbus_message_unref (message);
02723       _dbus_list_free_link (connection->disconnect_message_link);
02724     }
02725 
02726   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02727   _dbus_condvar_free_at_location (&connection->io_path_cond);
02728 
02729   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02730   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02731 
02732   _dbus_mutex_free_at_location (&connection->slot_mutex);
02733 
02734   _dbus_mutex_free_at_location (&connection->mutex);
02735   
02736   dbus_free (connection);
02737 }
02738 
02758 void
02759 dbus_connection_unref (DBusConnection *connection)
02760 {
02761   dbus_bool_t last_unref;
02762 
02763   _dbus_return_if_fail (connection != NULL);
02764   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02765 
02766   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02767 
02768   if (last_unref)
02769     {
02770 #ifndef DBUS_DISABLE_CHECKS
02771       if (_dbus_transport_get_is_connected (connection->transport))
02772         {
02773           _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",
02774                                    connection->shareable ?
02775                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02776                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02777           return;
02778         }
02779 #endif
02780       _dbus_connection_last_unref (connection);
02781     }
02782 }
02783 
02784 /*
02785  * Note that the transport can disconnect itself (other end drops us)
02786  * and in that case this function never runs. So this function must
02787  * not do anything more than disconnect the transport and update the
02788  * dispatch status.
02789  * 
02790  * If the transport self-disconnects, then we assume someone will
02791  * dispatch the connection to cause the dispatch status update.
02792  */
02793 static void
02794 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02795 {
02796   DBusDispatchStatus status;
02797 
02798   HAVE_LOCK_CHECK (connection);
02799   
02800   _dbus_verbose ("Disconnecting %p\n", connection);
02801 
02802   /* We need to ref because update_dispatch_status_and_unlock will unref
02803    * the connection if it was shared and libdbus was the only remaining
02804    * refcount holder.
02805    */
02806   _dbus_connection_ref_unlocked (connection);
02807   
02808   _dbus_transport_disconnect (connection->transport);
02809 
02810   /* This has the side effect of queuing the disconnect message link
02811    * (unless we don't have enough memory, possibly, so don't assert it).
02812    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02813    * should never again return the newly-disconnected connection.
02814    *
02815    * However, we only unref the shared connection and exit_on_disconnect when
02816    * the disconnect message reaches the head of the message queue,
02817    * NOT when it's first queued.
02818    */
02819   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02820 
02821   /* This calls out to user code */
02822   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02823 
02824   /* Could also call out to user code */
02825   dbus_connection_unref (connection);
02826 }
02827 
02870 void
02871 dbus_connection_close (DBusConnection *connection)
02872 {
02873   _dbus_return_if_fail (connection != NULL);
02874   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02875 
02876   CONNECTION_LOCK (connection);
02877 
02878 #ifndef DBUS_DISABLE_CHECKS
02879   if (connection->shareable)
02880     {
02881       CONNECTION_UNLOCK (connection);
02882 
02883       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02884       return;
02885     }
02886 #endif
02887   
02888   _dbus_connection_close_possibly_shared_and_unlock (connection);
02889 }
02890 
02891 static dbus_bool_t
02892 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02893 {
02894   HAVE_LOCK_CHECK (connection);
02895   return _dbus_transport_get_is_connected (connection->transport);
02896 }
02897 
02911 dbus_bool_t
02912 dbus_connection_get_is_connected (DBusConnection *connection)
02913 {
02914   dbus_bool_t res;
02915 
02916   _dbus_return_val_if_fail (connection != NULL, FALSE);
02917   
02918   CONNECTION_LOCK (connection);
02919   res = _dbus_connection_get_is_connected_unlocked (connection);
02920   CONNECTION_UNLOCK (connection);
02921   
02922   return res;
02923 }
02924 
02933 dbus_bool_t
02934 dbus_connection_get_is_authenticated (DBusConnection *connection)
02935 {
02936   dbus_bool_t res;
02937 
02938   _dbus_return_val_if_fail (connection != NULL, FALSE);
02939   
02940   CONNECTION_LOCK (connection);
02941   res = _dbus_transport_get_is_authenticated (connection->transport);
02942   CONNECTION_UNLOCK (connection);
02943   
02944   return res;
02945 }
02946 
02967 dbus_bool_t
02968 dbus_connection_get_is_anonymous (DBusConnection *connection)
02969 {
02970   dbus_bool_t res;
02971 
02972   _dbus_return_val_if_fail (connection != NULL, FALSE);
02973   
02974   CONNECTION_LOCK (connection);
02975   res = _dbus_transport_get_is_anonymous (connection->transport);
02976   CONNECTION_UNLOCK (connection);
02977   
02978   return res;
02979 }
02980 
03012 char*
03013 dbus_connection_get_server_id (DBusConnection *connection)
03014 {
03015   char *id;
03016 
03017   _dbus_return_val_if_fail (connection != NULL, NULL);
03018 
03019   CONNECTION_LOCK (connection);
03020   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03021   CONNECTION_UNLOCK (connection);
03022 
03023   return id;
03024 }
03025 
03043 dbus_bool_t
03044 dbus_connection_can_send_type(DBusConnection *connection,
03045                                   int type)
03046 {
03047   _dbus_return_val_if_fail (connection != NULL, FALSE);
03048 
03049   if (!dbus_type_is_valid (type))
03050     return FALSE;
03051 
03052   if (type != DBUS_TYPE_UNIX_FD)
03053     return TRUE;
03054 
03055 #ifdef HAVE_UNIX_FD_PASSING
03056   {
03057     dbus_bool_t b;
03058 
03059     CONNECTION_LOCK(connection);
03060     b = _dbus_transport_can_pass_unix_fd(connection->transport);
03061     CONNECTION_UNLOCK(connection);
03062 
03063     return b;
03064   }
03065 #endif
03066 
03067   return FALSE;
03068 }
03069 
03083 void
03084 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03085                                         dbus_bool_t     exit_on_disconnect)
03086 {
03087   _dbus_return_if_fail (connection != NULL);
03088 
03089   CONNECTION_LOCK (connection);
03090   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03091   CONNECTION_UNLOCK (connection);
03092 }
03093 
03103 DBusPreallocatedSend*
03104 dbus_connection_preallocate_send (DBusConnection *connection)
03105 {
03106   DBusPreallocatedSend *preallocated;
03107 
03108   _dbus_return_val_if_fail (connection != NULL, NULL);
03109 
03110   CONNECTION_LOCK (connection);
03111   
03112   preallocated =
03113     _dbus_connection_preallocate_send_unlocked (connection);
03114 
03115   CONNECTION_UNLOCK (connection);
03116 
03117   return preallocated;
03118 }
03119 
03129 void
03130 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03131                                         DBusPreallocatedSend *preallocated)
03132 {
03133   _dbus_return_if_fail (connection != NULL);
03134   _dbus_return_if_fail (preallocated != NULL);  
03135   _dbus_return_if_fail (connection == preallocated->connection);
03136 
03137   _dbus_list_free_link (preallocated->queue_link);
03138   _dbus_counter_unref (preallocated->counter_link->data);
03139   _dbus_list_free_link (preallocated->counter_link);
03140   dbus_free (preallocated);
03141 }
03142 
03155 void
03156 dbus_connection_send_preallocated (DBusConnection       *connection,
03157                                    DBusPreallocatedSend *preallocated,
03158                                    DBusMessage          *message,
03159                                    dbus_uint32_t        *client_serial)
03160 {
03161   _dbus_return_if_fail (connection != NULL);
03162   _dbus_return_if_fail (preallocated != NULL);
03163   _dbus_return_if_fail (message != NULL);
03164   _dbus_return_if_fail (preallocated->connection == connection);
03165   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03166                         dbus_message_get_member (message) != NULL);
03167   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03168                         (dbus_message_get_interface (message) != NULL &&
03169                          dbus_message_get_member (message) != NULL));
03170 
03171   CONNECTION_LOCK (connection);
03172 
03173 #ifdef HAVE_UNIX_FD_PASSING
03174 
03175   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03176       message->n_unix_fds > 0)
03177     {
03178       /* Refuse to send fds on a connection that cannot handle
03179          them. Unfortunately we cannot return a proper error here, so
03180          the best we can is just return. */
03181       CONNECTION_UNLOCK (connection);
03182       return;
03183     }
03184 
03185 #endif
03186 
03187   _dbus_connection_send_preallocated_and_unlock (connection,
03188                                                  preallocated,
03189                                                  message, client_serial);
03190 }
03191 
03192 static dbus_bool_t
03193 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03194                                           DBusMessage    *message,
03195                                           dbus_uint32_t  *client_serial)
03196 {
03197   DBusPreallocatedSend *preallocated;
03198 
03199   _dbus_assert (connection != NULL);
03200   _dbus_assert (message != NULL);
03201   
03202   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03203   if (preallocated == NULL)
03204     return FALSE;
03205 
03206   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03207                                                          preallocated,
03208                                                          message,
03209                                                          client_serial);
03210   return TRUE;
03211 }
03212 
03240 dbus_bool_t
03241 dbus_connection_send (DBusConnection *connection,
03242                       DBusMessage    *message,
03243                       dbus_uint32_t  *serial)
03244 {
03245   _dbus_return_val_if_fail (connection != NULL, FALSE);
03246   _dbus_return_val_if_fail (message != NULL, FALSE);
03247 
03248   CONNECTION_LOCK (connection);
03249 
03250 #ifdef HAVE_UNIX_FD_PASSING
03251 
03252   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03253       message->n_unix_fds > 0)
03254     {
03255       /* Refuse to send fds on a connection that cannot handle
03256          them. Unfortunately we cannot return a proper error here, so
03257          the best we can is just return. */
03258       CONNECTION_UNLOCK (connection);
03259       return FALSE;
03260     }
03261 
03262 #endif
03263 
03264   return _dbus_connection_send_and_unlock (connection,
03265                                            message,
03266                                            serial);
03267 }
03268 
03269 static dbus_bool_t
03270 reply_handler_timeout (void *data)
03271 {
03272   DBusConnection *connection;
03273   DBusDispatchStatus status;
03274   DBusPendingCall *pending = data;
03275 
03276   connection = _dbus_pending_call_get_connection_and_lock (pending);
03277   _dbus_connection_ref_unlocked (connection);
03278 
03279   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03280                                                    connection);
03281   _dbus_connection_remove_timeout_unlocked (connection,
03282                                             _dbus_pending_call_get_timeout_unlocked (pending));
03283   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03284 
03285   _dbus_verbose ("middle\n");
03286   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03287 
03288   /* Unlocks, and calls out to user code */
03289   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03290   dbus_connection_unref (connection);
03291   
03292   return TRUE;
03293 }
03294 
03337 dbus_bool_t
03338 dbus_connection_send_with_reply (DBusConnection     *connection,
03339                                  DBusMessage        *message,
03340                                  DBusPendingCall   **pending_return,
03341                                  int                 timeout_milliseconds)
03342 {
03343   DBusPendingCall *pending;
03344   dbus_int32_t serial = -1;
03345   DBusDispatchStatus status;
03346 
03347   _dbus_return_val_if_fail (connection != NULL, FALSE);
03348   _dbus_return_val_if_fail (message != NULL, FALSE);
03349   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03350 
03351   if (pending_return)
03352     *pending_return = NULL;
03353 
03354   CONNECTION_LOCK (connection);
03355 
03356 #ifdef HAVE_UNIX_FD_PASSING
03357 
03358   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03359       message->n_unix_fds > 0)
03360     {
03361       /* Refuse to send fds on a connection that cannot handle
03362          them. Unfortunately we cannot return a proper error here, so
03363          the best we can do is return TRUE but leave *pending_return
03364          as NULL. */
03365       CONNECTION_UNLOCK (connection);
03366       return TRUE;
03367     }
03368 
03369 #endif
03370 
03371    if (!_dbus_connection_get_is_connected_unlocked (connection))
03372     {
03373       CONNECTION_UNLOCK (connection);
03374 
03375       return TRUE;
03376     }
03377 
03378   pending = _dbus_pending_call_new_unlocked (connection,
03379                                              timeout_milliseconds,
03380                                              reply_handler_timeout);
03381 
03382   if (pending == NULL)
03383     {
03384       CONNECTION_UNLOCK (connection);
03385       return FALSE;
03386     }
03387 
03388   /* Assign a serial to the message */
03389   serial = dbus_message_get_serial (message);
03390   if (serial == 0)
03391     {
03392       serial = _dbus_connection_get_next_client_serial (connection);
03393       dbus_message_set_serial (message, serial);
03394     }
03395 
03396   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03397     goto error;
03398     
03399   /* Insert the serial in the pending replies hash;
03400    * hash takes a refcount on DBusPendingCall.
03401    * Also, add the timeout.
03402    */
03403   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03404                                                       pending))
03405     goto error;
03406  
03407   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03408     {
03409       _dbus_connection_detach_pending_call_and_unlock (connection,
03410                                                        pending);
03411       goto error_unlocked;
03412     }
03413 
03414   if (pending_return)
03415     *pending_return = pending; /* hand off refcount */
03416   else
03417     {
03418       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03419       /* we still have a ref to the pending call in this case, we unref
03420        * after unlocking, below
03421        */
03422     }
03423 
03424   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03425 
03426   /* this calls out to user code */
03427   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03428 
03429   if (pending_return == NULL)
03430     dbus_pending_call_unref (pending);
03431   
03432   return TRUE;
03433 
03434  error:
03435   CONNECTION_UNLOCK (connection);
03436  error_unlocked:
03437   dbus_pending_call_unref (pending);
03438   return FALSE;
03439 }
03440 
03473 DBusMessage*
03474 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03475                                            DBusMessage        *message,
03476                                            int                 timeout_milliseconds,
03477                                            DBusError          *error)
03478 {
03479   DBusMessage *reply;
03480   DBusPendingCall *pending;
03481 
03482   _dbus_return_val_if_fail (connection != NULL, NULL);
03483   _dbus_return_val_if_fail (message != NULL, NULL);
03484   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03485   _dbus_return_val_if_error_is_set (error, NULL);
03486 
03487 #ifdef HAVE_UNIX_FD_PASSING
03488 
03489   CONNECTION_LOCK (connection);
03490   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03491       message->n_unix_fds > 0)
03492     {
03493       CONNECTION_UNLOCK (connection);
03494       dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03495       return NULL;
03496     }
03497   CONNECTION_UNLOCK (connection);
03498 
03499 #endif
03500 
03501   if (!dbus_connection_send_with_reply (connection, message,
03502                                         &pending, timeout_milliseconds))
03503     {
03504       _DBUS_SET_OOM (error);
03505       return NULL;
03506     }
03507 
03508   if (pending == NULL)
03509     {
03510       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03511       return NULL;
03512     }
03513   
03514   dbus_pending_call_block (pending);
03515 
03516   reply = dbus_pending_call_steal_reply (pending);
03517   dbus_pending_call_unref (pending);
03518 
03519   /* call_complete_and_unlock() called from pending_call_block() should
03520    * always fill this in.
03521    */
03522   _dbus_assert (reply != NULL);
03523   
03524    if (dbus_set_error_from_message (error, reply))
03525     {
03526       dbus_message_unref (reply);
03527       return NULL;
03528     }
03529   else
03530     return reply;
03531 }
03532 
03541 static DBusDispatchStatus
03542 _dbus_connection_flush_unlocked (DBusConnection *connection)
03543 {
03544   /* We have to specify DBUS_ITERATION_DO_READING here because
03545    * otherwise we could have two apps deadlock if they are both doing
03546    * a flush(), and the kernel buffers fill up. This could change the
03547    * dispatch status.
03548    */
03549   DBusDispatchStatus status;
03550 
03551   HAVE_LOCK_CHECK (connection);
03552   
03553   while (connection->n_outgoing > 0 &&
03554          _dbus_connection_get_is_connected_unlocked (connection))
03555     {
03556       _dbus_verbose ("doing iteration in\n");
03557       HAVE_LOCK_CHECK (connection);
03558       _dbus_connection_do_iteration_unlocked (connection,
03559                                               NULL,
03560                                               DBUS_ITERATION_DO_READING |
03561                                               DBUS_ITERATION_DO_WRITING |
03562                                               DBUS_ITERATION_BLOCK,
03563                                               -1);
03564     }
03565 
03566   HAVE_LOCK_CHECK (connection);
03567   _dbus_verbose ("middle\n");
03568   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03569 
03570   HAVE_LOCK_CHECK (connection);
03571   return status;
03572 }
03573 
03579 void
03580 dbus_connection_flush (DBusConnection *connection)
03581 {
03582   /* We have to specify DBUS_ITERATION_DO_READING here because
03583    * otherwise we could have two apps deadlock if they are both doing
03584    * a flush(), and the kernel buffers fill up. This could change the
03585    * dispatch status.
03586    */
03587   DBusDispatchStatus status;
03588 
03589   _dbus_return_if_fail (connection != NULL);
03590   
03591   CONNECTION_LOCK (connection);
03592 
03593   status = _dbus_connection_flush_unlocked (connection);
03594   
03595   HAVE_LOCK_CHECK (connection);
03596   /* Unlocks and calls out to user code */
03597   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03598 
03599   _dbus_verbose ("end\n");
03600 }
03601 
03612 static dbus_bool_t
03613 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03614                                      int             timeout_milliseconds, 
03615                                      dbus_bool_t     dispatch)
03616 {
03617   DBusDispatchStatus dstatus;
03618   dbus_bool_t progress_possible;
03619 
03620   /* Need to grab a ref here in case we're a private connection and
03621    * the user drops the last ref in a handler we call; see bug 
03622    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03623    */
03624   dbus_connection_ref (connection);
03625   dstatus = dbus_connection_get_dispatch_status (connection);
03626 
03627   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03628     {
03629       _dbus_verbose ("doing dispatch\n");
03630       dbus_connection_dispatch (connection);
03631       CONNECTION_LOCK (connection);
03632     }
03633   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03634     {
03635       _dbus_verbose ("pausing for memory\n");
03636       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03637       CONNECTION_LOCK (connection);
03638     }
03639   else
03640     {
03641       CONNECTION_LOCK (connection);
03642       if (_dbus_connection_get_is_connected_unlocked (connection))
03643         {
03644           _dbus_verbose ("doing iteration\n");
03645           _dbus_connection_do_iteration_unlocked (connection,
03646                                                   NULL,
03647                                                   DBUS_ITERATION_DO_READING |
03648                                                   DBUS_ITERATION_DO_WRITING |
03649                                                   DBUS_ITERATION_BLOCK,
03650                                                   timeout_milliseconds);
03651         }
03652     }
03653   
03654   HAVE_LOCK_CHECK (connection);
03655   /* If we can dispatch, we can make progress until the Disconnected message
03656    * has been processed; if we can only read/write, we can make progress
03657    * as long as the transport is open.
03658    */
03659   if (dispatch)
03660     progress_possible = connection->n_incoming != 0 ||
03661       connection->disconnect_message_link != NULL;
03662   else
03663     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03664 
03665   CONNECTION_UNLOCK (connection);
03666 
03667   dbus_connection_unref (connection);
03668 
03669   return progress_possible; /* TRUE if we can make more progress */
03670 }
03671 
03672 
03707 dbus_bool_t
03708 dbus_connection_read_write_dispatch (DBusConnection *connection,
03709                                      int             timeout_milliseconds)
03710 {
03711   _dbus_return_val_if_fail (connection != NULL, FALSE);
03712   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03713    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03714 }
03715 
03739 dbus_bool_t 
03740 dbus_connection_read_write (DBusConnection *connection, 
03741                             int             timeout_milliseconds) 
03742 { 
03743   _dbus_return_val_if_fail (connection != NULL, FALSE);
03744   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03745    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03746 }
03747 
03748 /* We need to call this anytime we pop the head of the queue, and then
03749  * update_dispatch_status_and_unlock needs to be called afterward
03750  * which will "process" the disconnected message and set
03751  * disconnected_message_processed.
03752  */
03753 static void
03754 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03755                                              DBusMessage    *head_of_queue)
03756 {
03757   HAVE_LOCK_CHECK (connection);
03758 
03759   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03760   if (connection->disconnect_message_link == NULL &&
03761       dbus_message_is_signal (head_of_queue,
03762                               DBUS_INTERFACE_LOCAL,
03763                               "Disconnected"))
03764     {
03765       connection->disconnected_message_arrived = TRUE;
03766     }
03767 }
03768 
03788 DBusMessage*
03789 dbus_connection_borrow_message (DBusConnection *connection)
03790 {
03791   DBusDispatchStatus status;
03792   DBusMessage *message;
03793 
03794   _dbus_return_val_if_fail (connection != NULL, NULL);
03795 
03796   _dbus_verbose ("start\n");
03797   
03798   /* this is called for the side effect that it queues
03799    * up any messages from the transport
03800    */
03801   status = dbus_connection_get_dispatch_status (connection);
03802   if (status != DBUS_DISPATCH_DATA_REMAINS)
03803     return NULL;
03804   
03805   CONNECTION_LOCK (connection);
03806 
03807   _dbus_connection_acquire_dispatch (connection);
03808 
03809   /* While a message is outstanding, the dispatch lock is held */
03810   _dbus_assert (connection->message_borrowed == NULL);
03811 
03812   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03813   
03814   message = connection->message_borrowed;
03815 
03816   check_disconnected_message_arrived_unlocked (connection, message);
03817   
03818   /* Note that we KEEP the dispatch lock until the message is returned */
03819   if (message == NULL)
03820     _dbus_connection_release_dispatch (connection);
03821 
03822   CONNECTION_UNLOCK (connection);
03823 
03824   /* We don't update dispatch status until it's returned or stolen */
03825   
03826   return message;
03827 }
03828 
03837 void
03838 dbus_connection_return_message (DBusConnection *connection,
03839                                 DBusMessage    *message)
03840 {
03841   DBusDispatchStatus status;
03842   
03843   _dbus_return_if_fail (connection != NULL);
03844   _dbus_return_if_fail (message != NULL);
03845   _dbus_return_if_fail (message == connection->message_borrowed);
03846   _dbus_return_if_fail (connection->dispatch_acquired);
03847   
03848   CONNECTION_LOCK (connection);
03849   
03850   _dbus_assert (message == connection->message_borrowed);
03851   
03852   connection->message_borrowed = NULL;
03853 
03854   _dbus_connection_release_dispatch (connection); 
03855 
03856   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03857   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03858 }
03859 
03869 void
03870 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03871                                         DBusMessage    *message)
03872 {
03873   DBusMessage *pop_message;
03874   DBusDispatchStatus status;
03875 
03876   _dbus_return_if_fail (connection != NULL);
03877   _dbus_return_if_fail (message != NULL);
03878   _dbus_return_if_fail (message == connection->message_borrowed);
03879   _dbus_return_if_fail (connection->dispatch_acquired);
03880   
03881   CONNECTION_LOCK (connection);
03882  
03883   _dbus_assert (message == connection->message_borrowed);
03884 
03885   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03886   _dbus_assert (message == pop_message);
03887   (void) pop_message; /* unused unless asserting */
03888 
03889   connection->n_incoming -= 1;
03890  
03891   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03892                  message, connection->n_incoming);
03893  
03894   connection->message_borrowed = NULL;
03895 
03896   _dbus_connection_release_dispatch (connection);
03897 
03898   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03899   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03900 }
03901 
03902 /* See dbus_connection_pop_message, but requires the caller to own
03903  * the lock before calling. May drop the lock while running.
03904  */
03905 static DBusList*
03906 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03907 {
03908   HAVE_LOCK_CHECK (connection);
03909   
03910   _dbus_assert (connection->message_borrowed == NULL);
03911   
03912   if (connection->n_incoming > 0)
03913     {
03914       DBusList *link;
03915 
03916       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03917       connection->n_incoming -= 1;
03918 
03919       _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03920                      link->data,
03921                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
03922                      dbus_message_get_path (link->data) ?
03923                      dbus_message_get_path (link->data) :
03924                      "no path",
03925                      dbus_message_get_interface (link->data) ?
03926                      dbus_message_get_interface (link->data) :
03927                      "no interface",
03928                      dbus_message_get_member (link->data) ?
03929                      dbus_message_get_member (link->data) :
03930                      "no member",
03931                      dbus_message_get_signature (link->data),
03932                      connection, connection->n_incoming);
03933 
03934       check_disconnected_message_arrived_unlocked (connection, link->data);
03935       
03936       return link;
03937     }
03938   else
03939     return NULL;
03940 }
03941 
03942 /* See dbus_connection_pop_message, but requires the caller to own
03943  * the lock before calling. May drop the lock while running.
03944  */
03945 static DBusMessage*
03946 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03947 {
03948   DBusList *link;
03949 
03950   HAVE_LOCK_CHECK (connection);
03951   
03952   link = _dbus_connection_pop_message_link_unlocked (connection);
03953 
03954   if (link != NULL)
03955     {
03956       DBusMessage *message;
03957       
03958       message = link->data;
03959       
03960       _dbus_list_free_link (link);
03961       
03962       return message;
03963     }
03964   else
03965     return NULL;
03966 }
03967 
03968 static void
03969 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03970                                                 DBusList       *message_link)
03971 {
03972   HAVE_LOCK_CHECK (connection);
03973   
03974   _dbus_assert (message_link != NULL);
03975   /* You can't borrow a message while a link is outstanding */
03976   _dbus_assert (connection->message_borrowed == NULL);
03977   /* We had to have the dispatch lock across the pop/putback */
03978   _dbus_assert (connection->dispatch_acquired);
03979 
03980   _dbus_list_prepend_link (&connection->incoming_messages,
03981                            message_link);
03982   connection->n_incoming += 1;
03983 
03984   _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
03985                  message_link->data,
03986                  dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
03987                  dbus_message_get_interface (message_link->data) ?
03988                  dbus_message_get_interface (message_link->data) :
03989                  "no interface",
03990                  dbus_message_get_member (message_link->data) ?
03991                  dbus_message_get_member (message_link->data) :
03992                  "no member",
03993                  dbus_message_get_signature (message_link->data),
03994                  connection, connection->n_incoming);
03995 }
03996 
04016 DBusMessage*
04017 dbus_connection_pop_message (DBusConnection *connection)
04018 {
04019   DBusMessage *message;
04020   DBusDispatchStatus status;
04021 
04022   _dbus_verbose ("start\n");
04023   
04024   /* this is called for the side effect that it queues
04025    * up any messages from the transport
04026    */
04027   status = dbus_connection_get_dispatch_status (connection);
04028   if (status != DBUS_DISPATCH_DATA_REMAINS)
04029     return NULL;
04030   
04031   CONNECTION_LOCK (connection);
04032   _dbus_connection_acquire_dispatch (connection);
04033   HAVE_LOCK_CHECK (connection);
04034   
04035   message = _dbus_connection_pop_message_unlocked (connection);
04036 
04037   _dbus_verbose ("Returning popped message %p\n", message);    
04038 
04039   _dbus_connection_release_dispatch (connection);
04040 
04041   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04042   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04043   
04044   return message;
04045 }
04046 
04054 static void
04055 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04056 {
04057   HAVE_LOCK_CHECK (connection);
04058 
04059   _dbus_connection_ref_unlocked (connection);
04060   CONNECTION_UNLOCK (connection);
04061   
04062   _dbus_verbose ("locking dispatch_mutex\n");
04063   _dbus_mutex_lock (connection->dispatch_mutex);
04064 
04065   while (connection->dispatch_acquired)
04066     {
04067       _dbus_verbose ("waiting for dispatch to be acquirable\n");
04068       _dbus_condvar_wait (connection->dispatch_cond, 
04069                           connection->dispatch_mutex);
04070     }
04071   
04072   _dbus_assert (!connection->dispatch_acquired);
04073 
04074   connection->dispatch_acquired = TRUE;
04075 
04076   _dbus_verbose ("unlocking dispatch_mutex\n");
04077   _dbus_mutex_unlock (connection->dispatch_mutex);
04078   
04079   CONNECTION_LOCK (connection);
04080   _dbus_connection_unref_unlocked (connection);
04081 }
04082 
04090 static void
04091 _dbus_connection_release_dispatch (DBusConnection *connection)
04092 {
04093   HAVE_LOCK_CHECK (connection);
04094   
04095   _dbus_verbose ("locking dispatch_mutex\n");
04096   _dbus_mutex_lock (connection->dispatch_mutex);
04097   
04098   _dbus_assert (connection->dispatch_acquired);
04099 
04100   connection->dispatch_acquired = FALSE;
04101   _dbus_condvar_wake_one (connection->dispatch_cond);
04102 
04103   _dbus_verbose ("unlocking dispatch_mutex\n");
04104   _dbus_mutex_unlock (connection->dispatch_mutex);
04105 }
04106 
04107 static void
04108 _dbus_connection_failed_pop (DBusConnection *connection,
04109                              DBusList       *message_link)
04110 {
04111   _dbus_list_prepend_link (&connection->incoming_messages,
04112                            message_link);
04113   connection->n_incoming += 1;
04114 }
04115 
04116 /* Note this may be called multiple times since we don't track whether we already did it */
04117 static void
04118 notify_disconnected_unlocked (DBusConnection *connection)
04119 {
04120   HAVE_LOCK_CHECK (connection);
04121 
04122   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04123    * connection from dbus_bus_get(). We make the same guarantee for
04124    * dbus_connection_open() but in a different way since we don't want to
04125    * unref right here; we instead check for connectedness before returning
04126    * the connection from the hash.
04127    */
04128   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04129 
04130   /* Dump the outgoing queue, we aren't going to be able to
04131    * send it now, and we'd like accessors like
04132    * dbus_connection_get_outgoing_size() to be accurate.
04133    */
04134   if (connection->n_outgoing > 0)
04135     {
04136       DBusList *link;
04137       
04138       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04139                      connection->n_outgoing);
04140       
04141       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04142         {
04143           _dbus_connection_message_sent_unlocked (connection, link->data);
04144         }
04145     } 
04146 }
04147 
04148 /* Note this may be called multiple times since we don't track whether we already did it */
04149 static DBusDispatchStatus
04150 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04151 {
04152   HAVE_LOCK_CHECK (connection);
04153   
04154   if (connection->disconnect_message_link != NULL)
04155     {
04156       _dbus_verbose ("Sending disconnect message\n");
04157       
04158       /* If we have pending calls, queue their timeouts - we want the Disconnected
04159        * to be the last message, after these timeouts.
04160        */
04161       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04162       
04163       /* We haven't sent the disconnect message already,
04164        * and all real messages have been queued up.
04165        */
04166       _dbus_connection_queue_synthesized_message_link (connection,
04167                                                        connection->disconnect_message_link);
04168       connection->disconnect_message_link = NULL;
04169 
04170       return DBUS_DISPATCH_DATA_REMAINS;
04171     }
04172 
04173   return DBUS_DISPATCH_COMPLETE;
04174 }
04175 
04176 static DBusDispatchStatus
04177 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04178 {
04179   HAVE_LOCK_CHECK (connection);
04180   
04181   if (connection->n_incoming > 0)
04182     return DBUS_DISPATCH_DATA_REMAINS;
04183   else if (!_dbus_transport_queue_messages (connection->transport))
04184     return DBUS_DISPATCH_NEED_MEMORY;
04185   else
04186     {
04187       DBusDispatchStatus status;
04188       dbus_bool_t is_connected;
04189       
04190       status = _dbus_transport_get_dispatch_status (connection->transport);
04191       is_connected = _dbus_transport_get_is_connected (connection->transport);
04192 
04193       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04194                      DISPATCH_STATUS_NAME (status), is_connected);
04195       
04196       if (!is_connected)
04197         {
04198           /* It's possible this would be better done by having an explicit
04199            * notification from _dbus_transport_disconnect() that would
04200            * synchronously do this, instead of waiting for the next dispatch
04201            * status check. However, probably not good to change until it causes
04202            * a problem.
04203            */
04204           notify_disconnected_unlocked (connection);
04205 
04206           /* I'm not sure this is needed; the idea is that we want to
04207            * queue the Disconnected only after we've read all the
04208            * messages, but if we're disconnected maybe we are guaranteed
04209            * to have read them all ?
04210            */
04211           if (status == DBUS_DISPATCH_COMPLETE)
04212             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04213         }
04214       
04215       if (status != DBUS_DISPATCH_COMPLETE)
04216         return status;
04217       else if (connection->n_incoming > 0)
04218         return DBUS_DISPATCH_DATA_REMAINS;
04219       else
04220         return DBUS_DISPATCH_COMPLETE;
04221     }
04222 }
04223 
04224 static void
04225 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04226                                                     DBusDispatchStatus new_status)
04227 {
04228   dbus_bool_t changed;
04229   DBusDispatchStatusFunction function;
04230   void *data;
04231 
04232   HAVE_LOCK_CHECK (connection);
04233 
04234   _dbus_connection_ref_unlocked (connection);
04235 
04236   changed = new_status != connection->last_dispatch_status;
04237 
04238   connection->last_dispatch_status = new_status;
04239 
04240   function = connection->dispatch_status_function;
04241   data = connection->dispatch_status_data;
04242 
04243   if (connection->disconnected_message_arrived &&
04244       !connection->disconnected_message_processed)
04245     {
04246       connection->disconnected_message_processed = TRUE;
04247       
04248       /* this does an unref, but we have a ref
04249        * so we should not run the finalizer here
04250        * inside the lock.
04251        */
04252       connection_forget_shared_unlocked (connection);
04253 
04254       if (connection->exit_on_disconnect)
04255         {
04256           CONNECTION_UNLOCK (connection);            
04257           
04258           _dbus_verbose ("Exiting on Disconnected signal\n");
04259           _dbus_exit (1);
04260           _dbus_assert_not_reached ("Call to exit() returned");
04261         }
04262     }
04263   
04264   /* We drop the lock */
04265   CONNECTION_UNLOCK (connection);
04266   
04267   if (changed && function)
04268     {
04269       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04270                      connection, new_status,
04271                      DISPATCH_STATUS_NAME (new_status));
04272       (* function) (connection, new_status, data);      
04273     }
04274   
04275   dbus_connection_unref (connection);
04276 }
04277 
04303 DBusDispatchStatus
04304 dbus_connection_get_dispatch_status (DBusConnection *connection)
04305 {
04306   DBusDispatchStatus status;
04307 
04308   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04309 
04310   _dbus_verbose ("start\n");
04311   
04312   CONNECTION_LOCK (connection);
04313 
04314   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04315   
04316   CONNECTION_UNLOCK (connection);
04317 
04318   return status;
04319 }
04320 
04324 static DBusHandlerResult
04325 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04326                                                  DBusMessage    *message)
04327 {
04328   dbus_bool_t sent = FALSE;
04329   DBusMessage *ret = NULL;
04330   DBusList *expire_link;
04331 
04332   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04333     {
04334       /* This means we're letting the bus route this message */
04335       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04336     }
04337 
04338   if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04339     {
04340       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04341     }
04342 
04343   /* Preallocate a linked-list link, so that if we need to dispose of a
04344    * message, we can attach it to the expired list */
04345   expire_link = _dbus_list_alloc_link (NULL);
04346 
04347   if (!expire_link)
04348     return DBUS_HANDLER_RESULT_NEED_MEMORY;
04349 
04350   if (dbus_message_is_method_call (message,
04351                                    DBUS_INTERFACE_PEER,
04352                                    "Ping"))
04353     {
04354       ret = dbus_message_new_method_return (message);
04355       if (ret == NULL)
04356         goto out;
04357 
04358       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04359     }
04360   else if (dbus_message_is_method_call (message,
04361                                         DBUS_INTERFACE_PEER,
04362                                         "GetMachineId"))
04363     {
04364       DBusString uuid;
04365       
04366       ret = dbus_message_new_method_return (message);
04367       if (ret == NULL)
04368         goto out;
04369 
04370       _dbus_string_init (&uuid);
04371       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04372         {
04373           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04374           if (dbus_message_append_args (ret,
04375                                         DBUS_TYPE_STRING, &v_STRING,
04376                                         DBUS_TYPE_INVALID))
04377             {
04378               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04379             }
04380         }
04381       _dbus_string_free (&uuid);
04382     }
04383   else
04384     {
04385       /* We need to bounce anything else with this interface, otherwise apps
04386        * could start extending the interface and when we added extensions
04387        * here to DBusConnection we'd break those apps.
04388        */
04389       ret = dbus_message_new_error (message,
04390                                     DBUS_ERROR_UNKNOWN_METHOD,
04391                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04392       if (ret == NULL)
04393         goto out;
04394 
04395       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04396     }
04397 
04398 out:
04399   if (ret == NULL)
04400     {
04401       _dbus_list_free_link (expire_link);
04402     }
04403   else
04404     {
04405       /* It'll be safe to unref the reply when we unlock */
04406       expire_link->data = ret;
04407       _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04408     }
04409 
04410   if (!sent)
04411     return DBUS_HANDLER_RESULT_NEED_MEMORY;
04412 
04413   return DBUS_HANDLER_RESULT_HANDLED;
04414 }
04415 
04422 static DBusHandlerResult
04423 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04424                                                            DBusMessage    *message)
04425 {
04426   /* We just run one filter for now but have the option to run more
04427      if the spec calls for it in the future */
04428 
04429   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04430 }
04431 
04474 DBusDispatchStatus
04475 dbus_connection_dispatch (DBusConnection *connection)
04476 {
04477   DBusMessage *message;
04478   DBusList *link, *filter_list_copy, *message_link;
04479   DBusHandlerResult result;
04480   DBusPendingCall *pending;
04481   dbus_int32_t reply_serial;
04482   DBusDispatchStatus status;
04483   dbus_bool_t found_object;
04484 
04485   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04486 
04487   _dbus_verbose ("\n");
04488   
04489   CONNECTION_LOCK (connection);
04490   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04491   if (status != DBUS_DISPATCH_DATA_REMAINS)
04492     {
04493       /* unlocks and calls out to user code */
04494       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04495       return status;
04496     }
04497   
04498   /* We need to ref the connection since the callback could potentially
04499    * drop the last ref to it
04500    */
04501   _dbus_connection_ref_unlocked (connection);
04502 
04503   _dbus_connection_acquire_dispatch (connection);
04504   HAVE_LOCK_CHECK (connection);
04505 
04506   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04507   if (message_link == NULL)
04508     {
04509       /* another thread dispatched our stuff */
04510 
04511       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04512       
04513       _dbus_connection_release_dispatch (connection);
04514 
04515       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04516 
04517       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04518       
04519       dbus_connection_unref (connection);
04520       
04521       return status;
04522     }
04523 
04524   message = message_link->data;
04525 
04526   _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04527                  message,
04528                  dbus_message_type_to_string (dbus_message_get_type (message)),
04529                  dbus_message_get_interface (message) ?
04530                  dbus_message_get_interface (message) :
04531                  "no interface",
04532                  dbus_message_get_member (message) ?
04533                  dbus_message_get_member (message) :
04534                  "no member",
04535                  dbus_message_get_signature (message));
04536 
04537   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04538   
04539   /* Pending call handling must be first, because if you do
04540    * dbus_connection_send_with_reply_and_block() or
04541    * dbus_pending_call_block() then no handlers/filters will be run on
04542    * the reply. We want consistent semantics in the case where we
04543    * dbus_connection_dispatch() the reply.
04544    */
04545   
04546   reply_serial = dbus_message_get_reply_serial (message);
04547   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04548                                          reply_serial);
04549   if (pending)
04550     {
04551       _dbus_verbose ("Dispatching a pending reply\n");
04552       complete_pending_call_and_unlock (connection, pending, message);
04553       pending = NULL; /* it's probably unref'd */
04554       
04555       CONNECTION_LOCK (connection);
04556       _dbus_verbose ("pending call completed in dispatch\n");
04557       result = DBUS_HANDLER_RESULT_HANDLED;
04558       goto out;
04559     }
04560 
04561   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04562   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04563     goto out;
04564  
04565   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04566     {
04567       _dbus_connection_release_dispatch (connection);
04568       HAVE_LOCK_CHECK (connection);
04569       
04570       _dbus_connection_failed_pop (connection, message_link);
04571 
04572       /* unlocks and calls user code */
04573       _dbus_connection_update_dispatch_status_and_unlock (connection,
04574                                                           DBUS_DISPATCH_NEED_MEMORY);
04575       dbus_connection_unref (connection);
04576       
04577       return DBUS_DISPATCH_NEED_MEMORY;
04578     }
04579   
04580   _dbus_list_foreach (&filter_list_copy,
04581                       (DBusForeachFunction)_dbus_message_filter_ref,
04582                       NULL);
04583 
04584   /* We're still protected from dispatch() reentrancy here
04585    * since we acquired the dispatcher
04586    */
04587   CONNECTION_UNLOCK (connection);
04588   
04589   link = _dbus_list_get_first_link (&filter_list_copy);
04590   while (link != NULL)
04591     {
04592       DBusMessageFilter *filter = link->data;
04593       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04594 
04595       if (filter->function == NULL)
04596         {
04597           _dbus_verbose ("  filter was removed in a callback function\n");
04598           link = next;
04599           continue;
04600         }
04601 
04602       _dbus_verbose ("  running filter on message %p\n", message);
04603       result = (* filter->function) (connection, message, filter->user_data);
04604 
04605       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04606         break;
04607 
04608       link = next;
04609     }
04610 
04611   _dbus_list_foreach (&filter_list_copy,
04612                       (DBusForeachFunction)_dbus_message_filter_unref,
04613                       NULL);
04614   _dbus_list_clear (&filter_list_copy);
04615   
04616   CONNECTION_LOCK (connection);
04617 
04618   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04619     {
04620       _dbus_verbose ("No memory\n");
04621       goto out;
04622     }
04623   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04624     {
04625       _dbus_verbose ("filter handled message in dispatch\n");
04626       goto out;
04627     }
04628 
04629   /* We're still protected from dispatch() reentrancy here
04630    * since we acquired the dispatcher
04631    */
04632   _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
04633                  message,
04634                  dbus_message_type_to_string (dbus_message_get_type (message)),
04635                  dbus_message_get_interface (message) ?
04636                  dbus_message_get_interface (message) :
04637                  "no interface",
04638                  dbus_message_get_member (message) ?
04639                  dbus_message_get_member (message) :
04640                  "no member",
04641                  dbus_message_get_signature (message));
04642 
04643   HAVE_LOCK_CHECK (connection);
04644   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04645                                                   message,
04646                                                   &found_object);
04647   
04648   CONNECTION_LOCK (connection);
04649 
04650   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04651     {
04652       _dbus_verbose ("object tree handled message in dispatch\n");
04653       goto out;
04654     }
04655 
04656   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04657     {
04658       DBusMessage *reply;
04659       DBusString str;
04660       DBusPreallocatedSend *preallocated;
04661       DBusList *expire_link;
04662 
04663       _dbus_verbose ("  sending error %s\n",
04664                      DBUS_ERROR_UNKNOWN_METHOD);
04665 
04666       if (!_dbus_string_init (&str))
04667         {
04668           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04669           _dbus_verbose ("no memory for error string in dispatch\n");
04670           goto out;
04671         }
04672               
04673       if (!_dbus_string_append_printf (&str,
04674                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04675                                        dbus_message_get_member (message),
04676                                        dbus_message_get_signature (message),
04677                                        dbus_message_get_interface (message)))
04678         {
04679           _dbus_string_free (&str);
04680           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04681           _dbus_verbose ("no memory for error string in dispatch\n");
04682           goto out;
04683         }
04684       
04685       reply = dbus_message_new_error (message,
04686                                       found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
04687                                       _dbus_string_get_const_data (&str));
04688       _dbus_string_free (&str);
04689 
04690       if (reply == NULL)
04691         {
04692           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04693           _dbus_verbose ("no memory for error reply in dispatch\n");
04694           goto out;
04695         }
04696 
04697       expire_link = _dbus_list_alloc_link (reply);
04698 
04699       if (expire_link == NULL)
04700         {
04701           dbus_message_unref (reply);
04702           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04703           _dbus_verbose ("no memory for error send in dispatch\n");
04704           goto out;
04705         }
04706 
04707       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04708 
04709       if (preallocated == NULL)
04710         {
04711           _dbus_list_free_link (expire_link);
04712           /* It's OK that this is finalized, because it hasn't been seen by
04713            * anything that could attach user callbacks */
04714           dbus_message_unref (reply);
04715           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04716           _dbus_verbose ("no memory for error send in dispatch\n");
04717           goto out;
04718         }
04719 
04720       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04721                                                              reply, NULL);
04722       /* reply will be freed when we release the lock */
04723       _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04724 
04725       result = DBUS_HANDLER_RESULT_HANDLED;
04726     }
04727   
04728   _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04729                  dbus_message_type_to_string (dbus_message_get_type (message)),
04730                  dbus_message_get_interface (message) ?
04731                  dbus_message_get_interface (message) :
04732                  "no interface",
04733                  dbus_message_get_member (message) ?
04734                  dbus_message_get_member (message) :
04735                  "no member",
04736                  dbus_message_get_signature (message),
04737                  connection);
04738   
04739  out:
04740   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04741     {
04742       _dbus_verbose ("out of memory\n");
04743       
04744       /* Put message back, and we'll start over.
04745        * Yes this means handlers must be idempotent if they
04746        * don't return HANDLED; c'est la vie.
04747        */
04748       _dbus_connection_putback_message_link_unlocked (connection,
04749                                                       message_link);
04750       /* now we don't want to free them */
04751       message_link = NULL;
04752       message = NULL;
04753     }
04754   else
04755     {
04756       _dbus_verbose (" ... done dispatching\n");
04757     }
04758 
04759   _dbus_connection_release_dispatch (connection);
04760   HAVE_LOCK_CHECK (connection);
04761 
04762   if (message != NULL)
04763     {
04764       /* We don't want this message to count in maximum message limits when
04765        * computing the dispatch status, below. We have to drop the lock
04766        * temporarily, because finalizing a message can trigger callbacks.
04767        *
04768        * We have a reference to the connection, and we don't use any cached
04769        * pointers to the connection's internals below this point, so it should
04770        * be safe to drop the lock and take it back. */
04771       CONNECTION_UNLOCK (connection);
04772       dbus_message_unref (message);
04773       CONNECTION_LOCK (connection);
04774     }
04775 
04776   if (message_link != NULL)
04777     _dbus_list_free_link (message_link);
04778 
04779   _dbus_verbose ("before final status update\n");
04780   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04781 
04782   /* unlocks and calls user code */
04783   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04784   
04785   dbus_connection_unref (connection);
04786   
04787   return status;
04788 }
04789 
04851 dbus_bool_t
04852 dbus_connection_set_watch_functions (DBusConnection              *connection,
04853                                      DBusAddWatchFunction         add_function,
04854                                      DBusRemoveWatchFunction      remove_function,
04855                                      DBusWatchToggledFunction     toggled_function,
04856                                      void                        *data,
04857                                      DBusFreeFunction             free_data_function)
04858 {
04859   dbus_bool_t retval;
04860 
04861   _dbus_return_val_if_fail (connection != NULL, FALSE);
04862   
04863   CONNECTION_LOCK (connection);
04864 
04865   retval = _dbus_watch_list_set_functions (connection->watches,
04866                                            add_function, remove_function,
04867                                            toggled_function,
04868                                            data, free_data_function);
04869 
04870   CONNECTION_UNLOCK (connection);
04871 
04872   return retval;
04873 }
04874 
04914 dbus_bool_t
04915 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04916                                          DBusAddTimeoutFunction     add_function,
04917                                          DBusRemoveTimeoutFunction  remove_function,
04918                                          DBusTimeoutToggledFunction toggled_function,
04919                                          void                      *data,
04920                                          DBusFreeFunction           free_data_function)
04921 {
04922   dbus_bool_t retval;
04923 
04924   _dbus_return_val_if_fail (connection != NULL, FALSE);
04925   
04926   CONNECTION_LOCK (connection);
04927 
04928   retval = _dbus_timeout_list_set_functions (connection->timeouts,
04929                                              add_function, remove_function,
04930                                              toggled_function,
04931                                              data, free_data_function);
04932 
04933   CONNECTION_UNLOCK (connection);
04934 
04935   return retval;
04936 }
04937 
04952 void
04953 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04954                                           DBusWakeupMainFunction     wakeup_main_function,
04955                                           void                      *data,
04956                                           DBusFreeFunction           free_data_function)
04957 {
04958   void *old_data;
04959   DBusFreeFunction old_free_data;
04960 
04961   _dbus_return_if_fail (connection != NULL);
04962   
04963   CONNECTION_LOCK (connection);
04964   old_data = connection->wakeup_main_data;
04965   old_free_data = connection->free_wakeup_main_data;
04966 
04967   connection->wakeup_main_function = wakeup_main_function;
04968   connection->wakeup_main_data = data;
04969   connection->free_wakeup_main_data = free_data_function;
04970   
04971   CONNECTION_UNLOCK (connection);
04972 
04973   /* Callback outside the lock */
04974   if (old_free_data)
04975     (*old_free_data) (old_data);
04976 }
04977 
04998 void
04999 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
05000                                               DBusDispatchStatusFunction  function,
05001                                               void                       *data,
05002                                               DBusFreeFunction            free_data_function)
05003 {
05004   void *old_data;
05005   DBusFreeFunction old_free_data;
05006 
05007   _dbus_return_if_fail (connection != NULL);
05008   
05009   CONNECTION_LOCK (connection);
05010   old_data = connection->dispatch_status_data;
05011   old_free_data = connection->free_dispatch_status_data;
05012 
05013   connection->dispatch_status_function = function;
05014   connection->dispatch_status_data = data;
05015   connection->free_dispatch_status_data = free_data_function;
05016   
05017   CONNECTION_UNLOCK (connection);
05018 
05019   /* Callback outside the lock */
05020   if (old_free_data)
05021     (*old_free_data) (old_data);
05022 }
05023 
05043 dbus_bool_t
05044 dbus_connection_get_unix_fd (DBusConnection *connection,
05045                              int            *fd)
05046 {
05047   _dbus_return_val_if_fail (connection != NULL, FALSE);
05048   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05049 
05050 #ifdef DBUS_WIN
05051   /* FIXME do this on a lower level */
05052   return FALSE;
05053 #endif
05054   
05055   return dbus_connection_get_socket(connection, fd);
05056 }
05057 
05073 dbus_bool_t
05074 dbus_connection_get_socket(DBusConnection              *connection,
05075                            int                         *fd)
05076 {
05077   dbus_bool_t retval;
05078 
05079   _dbus_return_val_if_fail (connection != NULL, FALSE);
05080   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05081   
05082   CONNECTION_LOCK (connection);
05083   
05084   retval = _dbus_transport_get_socket_fd (connection->transport,
05085                                           fd);
05086 
05087   CONNECTION_UNLOCK (connection);
05088 
05089   return retval;
05090 }
05091 
05092 
05115 dbus_bool_t
05116 dbus_connection_get_unix_user (DBusConnection *connection,
05117                                unsigned long  *uid)
05118 {
05119   dbus_bool_t result;
05120 
05121   _dbus_return_val_if_fail (connection != NULL, FALSE);
05122   _dbus_return_val_if_fail (uid != NULL, FALSE);
05123   
05124   CONNECTION_LOCK (connection);
05125 
05126   if (!_dbus_transport_get_is_authenticated (connection->transport))
05127     result = FALSE;
05128   else
05129     result = _dbus_transport_get_unix_user (connection->transport,
05130                                             uid);
05131 
05132 #ifdef DBUS_WIN
05133   _dbus_assert (!result);
05134 #endif
05135   
05136   CONNECTION_UNLOCK (connection);
05137 
05138   return result;
05139 }
05140 
05151 dbus_bool_t
05152 dbus_connection_get_unix_process_id (DBusConnection *connection,
05153                                      unsigned long  *pid)
05154 {
05155   dbus_bool_t result;
05156 
05157   _dbus_return_val_if_fail (connection != NULL, FALSE);
05158   _dbus_return_val_if_fail (pid != NULL, FALSE);
05159   
05160   CONNECTION_LOCK (connection);
05161 
05162   if (!_dbus_transport_get_is_authenticated (connection->transport))
05163     result = FALSE;
05164   else
05165     result = _dbus_transport_get_unix_process_id (connection->transport,
05166                                                   pid);
05167 
05168   CONNECTION_UNLOCK (connection);
05169 
05170   return result;
05171 }
05172 
05183 dbus_bool_t
05184 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05185                                             void          **data,
05186                                             dbus_int32_t   *data_size)
05187 {
05188   dbus_bool_t result;
05189 
05190   _dbus_return_val_if_fail (connection != NULL, FALSE);
05191   _dbus_return_val_if_fail (data != NULL, FALSE);
05192   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05193   
05194   CONNECTION_LOCK (connection);
05195 
05196   if (!_dbus_transport_get_is_authenticated (connection->transport))
05197     result = FALSE;
05198   else
05199     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05200                                                          data,
05201                                                          data_size);
05202   CONNECTION_UNLOCK (connection);
05203 
05204   return result;
05205 }
05206 
05229 void
05230 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05231                                         DBusAllowUnixUserFunction   function,
05232                                         void                       *data,
05233                                         DBusFreeFunction            free_data_function)
05234 {
05235   void *old_data = NULL;
05236   DBusFreeFunction old_free_function = NULL;
05237 
05238   _dbus_return_if_fail (connection != NULL);
05239   
05240   CONNECTION_LOCK (connection);
05241   _dbus_transport_set_unix_user_function (connection->transport,
05242                                           function, data, free_data_function,
05243                                           &old_data, &old_free_function);
05244   CONNECTION_UNLOCK (connection);
05245 
05246   if (old_free_function != NULL)
05247     (* old_free_function) (old_data);
05248 }
05249 
05281 dbus_bool_t
05282 dbus_connection_get_windows_user (DBusConnection             *connection,
05283                                   char                      **windows_sid_p)
05284 {
05285   dbus_bool_t result;
05286 
05287   _dbus_return_val_if_fail (connection != NULL, FALSE);
05288   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05289   
05290   CONNECTION_LOCK (connection);
05291 
05292   if (!_dbus_transport_get_is_authenticated (connection->transport))
05293     result = FALSE;
05294   else
05295     result = _dbus_transport_get_windows_user (connection->transport,
05296                                                windows_sid_p);
05297 
05298 #ifdef DBUS_UNIX
05299   _dbus_assert (!result);
05300 #endif
05301   
05302   CONNECTION_UNLOCK (connection);
05303 
05304   return result;
05305 }
05306 
05328 void
05329 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05330                                            DBusAllowWindowsUserFunction function,
05331                                            void                        *data,
05332                                            DBusFreeFunction             free_data_function)
05333 {
05334   void *old_data = NULL;
05335   DBusFreeFunction old_free_function = NULL;
05336 
05337   _dbus_return_if_fail (connection != NULL);
05338   
05339   CONNECTION_LOCK (connection);
05340   _dbus_transport_set_windows_user_function (connection->transport,
05341                                              function, data, free_data_function,
05342                                              &old_data, &old_free_function);
05343   CONNECTION_UNLOCK (connection);
05344 
05345   if (old_free_function != NULL)
05346     (* old_free_function) (old_data);
05347 }
05348 
05375 void
05376 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05377                                      dbus_bool_t                 value)
05378 {
05379   _dbus_return_if_fail (connection != NULL);
05380   
05381   CONNECTION_LOCK (connection);
05382   _dbus_transport_set_allow_anonymous (connection->transport, value);
05383   CONNECTION_UNLOCK (connection);
05384 }
05385 
05403 void
05404 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05405                                          dbus_bool_t                 value)
05406 {
05407   _dbus_return_if_fail (connection != NULL);
05408   
05409   CONNECTION_LOCK (connection);
05410   connection->route_peer_messages = TRUE;
05411   CONNECTION_UNLOCK (connection);
05412 }
05413 
05435 dbus_bool_t
05436 dbus_connection_add_filter (DBusConnection            *connection,
05437                             DBusHandleMessageFunction  function,
05438                             void                      *user_data,
05439                             DBusFreeFunction           free_data_function)
05440 {
05441   DBusMessageFilter *filter;
05442   
05443   _dbus_return_val_if_fail (connection != NULL, FALSE);
05444   _dbus_return_val_if_fail (function != NULL, FALSE);
05445 
05446   filter = dbus_new0 (DBusMessageFilter, 1);
05447   if (filter == NULL)
05448     return FALSE;
05449 
05450   _dbus_atomic_inc (&filter->refcount);
05451 
05452   CONNECTION_LOCK (connection);
05453 
05454   if (!_dbus_list_append (&connection->filter_list,
05455                           filter))
05456     {
05457       _dbus_message_filter_unref (filter);
05458       CONNECTION_UNLOCK (connection);
05459       return FALSE;
05460     }
05461 
05462   /* Fill in filter after all memory allocated,
05463    * so we don't run the free_user_data_function
05464    * if the add_filter() fails
05465    */
05466   
05467   filter->function = function;
05468   filter->user_data = user_data;
05469   filter->free_user_data_function = free_data_function;
05470         
05471   CONNECTION_UNLOCK (connection);
05472   return TRUE;
05473 }
05474 
05487 void
05488 dbus_connection_remove_filter (DBusConnection            *connection,
05489                                DBusHandleMessageFunction  function,
05490                                void                      *user_data)
05491 {
05492   DBusList *link;
05493   DBusMessageFilter *filter;
05494   
05495   _dbus_return_if_fail (connection != NULL);
05496   _dbus_return_if_fail (function != NULL);
05497   
05498   CONNECTION_LOCK (connection);
05499 
05500   filter = NULL;
05501   
05502   link = _dbus_list_get_last_link (&connection->filter_list);
05503   while (link != NULL)
05504     {
05505       filter = link->data;
05506 
05507       if (filter->function == function &&
05508           filter->user_data == user_data)
05509         {
05510           _dbus_list_remove_link (&connection->filter_list, link);
05511           filter->function = NULL;
05512           
05513           break;
05514         }
05515         
05516       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05517       filter = NULL;
05518     }
05519   
05520   CONNECTION_UNLOCK (connection);
05521 
05522 #ifndef DBUS_DISABLE_CHECKS
05523   if (filter == NULL)
05524     {
05525       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05526                                function, user_data);
05527       return;
05528     }
05529 #endif
05530   
05531   /* Call application code */
05532   if (filter->free_user_data_function)
05533     (* filter->free_user_data_function) (filter->user_data);
05534 
05535   filter->free_user_data_function = NULL;
05536   filter->user_data = NULL;
05537   
05538   _dbus_message_filter_unref (filter);
05539 }
05540 
05556 static dbus_bool_t
05557 _dbus_connection_register_object_path (DBusConnection              *connection,
05558                                        dbus_bool_t                  fallback,
05559                                        const char                  *path,
05560                                        const DBusObjectPathVTable  *vtable,
05561                                        void                        *user_data,
05562                                        DBusError                   *error)
05563 {
05564   char **decomposed_path;
05565   dbus_bool_t retval;
05566 
05567   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05568     return FALSE;
05569 
05570   CONNECTION_LOCK (connection);
05571 
05572   retval = _dbus_object_tree_register (connection->objects,
05573                                        fallback,
05574                                        (const char **) decomposed_path, vtable,
05575                                        user_data, error);
05576 
05577   CONNECTION_UNLOCK (connection);
05578 
05579   dbus_free_string_array (decomposed_path);
05580 
05581   return retval;
05582 }
05583 
05596 dbus_bool_t
05597 dbus_connection_try_register_object_path (DBusConnection              *connection,
05598                                           const char                  *path,
05599                                           const DBusObjectPathVTable  *vtable,
05600                                           void                        *user_data,
05601                                           DBusError                   *error)
05602 {
05603   _dbus_return_val_if_fail (connection != NULL, FALSE);
05604   _dbus_return_val_if_fail (path != NULL, FALSE);
05605   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05606   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05607 
05608   return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
05609 }
05610 
05626 dbus_bool_t
05627 dbus_connection_register_object_path (DBusConnection              *connection,
05628                                       const char                  *path,
05629                                       const DBusObjectPathVTable  *vtable,
05630                                       void                        *user_data)
05631 {
05632   dbus_bool_t retval;
05633   DBusError error = DBUS_ERROR_INIT;
05634 
05635   _dbus_return_val_if_fail (connection != NULL, FALSE);
05636   _dbus_return_val_if_fail (path != NULL, FALSE);
05637   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05638   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05639 
05640   retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
05641 
05642   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05643     {
05644       _dbus_warn ("%s\n", error.message);
05645       dbus_error_free (&error);
05646       return FALSE;
05647     }
05648 
05649   return retval;
05650 }
05651 
05666 dbus_bool_t
05667 dbus_connection_try_register_fallback (DBusConnection              *connection,
05668                                        const char                  *path,
05669                                        const DBusObjectPathVTable  *vtable,
05670                                        void                        *user_data,
05671                                        DBusError                   *error)
05672 {
05673   _dbus_return_val_if_fail (connection != NULL, FALSE);
05674   _dbus_return_val_if_fail (path != NULL, FALSE);
05675   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05676   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05677 
05678   return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
05679 }
05680 
05698 dbus_bool_t
05699 dbus_connection_register_fallback (DBusConnection              *connection,
05700                                    const char                  *path,
05701                                    const DBusObjectPathVTable  *vtable,
05702                                    void                        *user_data)
05703 {
05704   dbus_bool_t retval;
05705   DBusError error = DBUS_ERROR_INIT;
05706 
05707   _dbus_return_val_if_fail (connection != NULL, FALSE);
05708   _dbus_return_val_if_fail (path != NULL, FALSE);
05709   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05710   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05711 
05712   retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
05713 
05714   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05715     {
05716       _dbus_warn ("%s\n", error.message);
05717       dbus_error_free (&error);
05718       return FALSE;
05719     }
05720 
05721   return retval;
05722 }
05723 
05733 dbus_bool_t
05734 dbus_connection_unregister_object_path (DBusConnection              *connection,
05735                                         const char                  *path)
05736 {
05737   char **decomposed_path;
05738 
05739   _dbus_return_val_if_fail (connection != NULL, FALSE);
05740   _dbus_return_val_if_fail (path != NULL, FALSE);
05741   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05742 
05743   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05744       return FALSE;
05745 
05746   CONNECTION_LOCK (connection);
05747 
05748   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05749 
05750   dbus_free_string_array (decomposed_path);
05751 
05752   return TRUE;
05753 }
05754 
05765 dbus_bool_t
05766 dbus_connection_get_object_path_data (DBusConnection *connection,
05767                                       const char     *path,
05768                                       void          **data_p)
05769 {
05770   char **decomposed_path;
05771 
05772   _dbus_return_val_if_fail (connection != NULL, FALSE);
05773   _dbus_return_val_if_fail (path != NULL, FALSE);
05774   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05775 
05776   *data_p = NULL;
05777   
05778   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05779     return FALSE;
05780   
05781   CONNECTION_LOCK (connection);
05782 
05783   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05784 
05785   CONNECTION_UNLOCK (connection);
05786 
05787   dbus_free_string_array (decomposed_path);
05788 
05789   return TRUE;
05790 }
05791 
05802 dbus_bool_t
05803 dbus_connection_list_registered (DBusConnection              *connection,
05804                                  const char                  *parent_path,
05805                                  char                      ***child_entries)
05806 {
05807   char **decomposed_path;
05808   dbus_bool_t retval;
05809   _dbus_return_val_if_fail (connection != NULL, FALSE);
05810   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05811   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05812   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05813 
05814   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05815     return FALSE;
05816 
05817   CONNECTION_LOCK (connection);
05818 
05819   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05820                                                          (const char **) decomposed_path,
05821                                                          child_entries);
05822   dbus_free_string_array (decomposed_path);
05823 
05824   return retval;
05825 }
05826 
05827 static DBusDataSlotAllocator slot_allocator;
05828 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05829 
05844 dbus_bool_t
05845 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05846 {
05847   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05848                                           &_DBUS_LOCK_NAME (connection_slots),
05849                                           slot_p);
05850 }
05851 
05863 void
05864 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05865 {
05866   _dbus_return_if_fail (*slot_p >= 0);
05867   
05868   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05869 }
05870 
05893 dbus_bool_t
05894 dbus_connection_set_data (DBusConnection   *connection,
05895                           dbus_int32_t      slot,
05896                           void             *data,
05897                           DBusFreeFunction  free_data_func)
05898 {
05899   DBusFreeFunction old_free_func;
05900   void *old_data;
05901   dbus_bool_t retval;
05902 
05903   _dbus_return_val_if_fail (connection != NULL, FALSE);
05904   _dbus_return_val_if_fail (slot >= 0, FALSE);
05905   
05906   SLOTS_LOCK (connection);
05907 
05908   retval = _dbus_data_slot_list_set (&slot_allocator,
05909                                      &connection->slot_list,
05910                                      slot, data, free_data_func,
05911                                      &old_free_func, &old_data);
05912   
05913   SLOTS_UNLOCK (connection);
05914 
05915   if (retval)
05916     {
05917       /* Do the actual free outside the connection lock */
05918       if (old_free_func)
05919         (* old_free_func) (old_data);
05920     }
05921 
05922   return retval;
05923 }
05924 
05942 void*
05943 dbus_connection_get_data (DBusConnection   *connection,
05944                           dbus_int32_t      slot)
05945 {
05946   void *res;
05947 
05948   _dbus_return_val_if_fail (connection != NULL, NULL);
05949   
05950   SLOTS_LOCK (connection);
05951 
05952   res = _dbus_data_slot_list_get (&slot_allocator,
05953                                   &connection->slot_list,
05954                                   slot);
05955   
05956   SLOTS_UNLOCK (connection);
05957 
05958   return res;
05959 }
05960 
05967 void
05968 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05969 {  
05970   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05971 }
05972 
05981 void
05982 dbus_connection_set_max_message_size (DBusConnection *connection,
05983                                       long            size)
05984 {
05985   _dbus_return_if_fail (connection != NULL);
05986   
05987   CONNECTION_LOCK (connection);
05988   _dbus_transport_set_max_message_size (connection->transport,
05989                                         size);
05990   CONNECTION_UNLOCK (connection);
05991 }
05992 
05999 long
06000 dbus_connection_get_max_message_size (DBusConnection *connection)
06001 {
06002   long res;
06003 
06004   _dbus_return_val_if_fail (connection != NULL, 0);
06005   
06006   CONNECTION_LOCK (connection);
06007   res = _dbus_transport_get_max_message_size (connection->transport);
06008   CONNECTION_UNLOCK (connection);
06009   return res;
06010 }
06011 
06020 void
06021 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06022                                           long            n)
06023 {
06024   _dbus_return_if_fail (connection != NULL);
06025 
06026   CONNECTION_LOCK (connection);
06027   _dbus_transport_set_max_message_unix_fds (connection->transport,
06028                                             n);
06029   CONNECTION_UNLOCK (connection);
06030 }
06031 
06038 long
06039 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06040 {
06041   long res;
06042 
06043   _dbus_return_val_if_fail (connection != NULL, 0);
06044 
06045   CONNECTION_LOCK (connection);
06046   res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06047   CONNECTION_UNLOCK (connection);
06048   return res;
06049 }
06050 
06076 void
06077 dbus_connection_set_max_received_size (DBusConnection *connection,
06078                                        long            size)
06079 {
06080   _dbus_return_if_fail (connection != NULL);
06081   
06082   CONNECTION_LOCK (connection);
06083   _dbus_transport_set_max_received_size (connection->transport,
06084                                          size);
06085   CONNECTION_UNLOCK (connection);
06086 }
06087 
06094 long
06095 dbus_connection_get_max_received_size (DBusConnection *connection)
06096 {
06097   long res;
06098 
06099   _dbus_return_val_if_fail (connection != NULL, 0);
06100   
06101   CONNECTION_LOCK (connection);
06102   res = _dbus_transport_get_max_received_size (connection->transport);
06103   CONNECTION_UNLOCK (connection);
06104   return res;
06105 }
06106 
06118 void
06119 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06120                                            long            n)
06121 {
06122   _dbus_return_if_fail (connection != NULL);
06123 
06124   CONNECTION_LOCK (connection);
06125   _dbus_transport_set_max_received_unix_fds (connection->transport,
06126                                              n);
06127   CONNECTION_UNLOCK (connection);
06128 }
06129 
06136 long
06137 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06138 {
06139   long res;
06140 
06141   _dbus_return_val_if_fail (connection != NULL, 0);
06142 
06143   CONNECTION_LOCK (connection);
06144   res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06145   CONNECTION_UNLOCK (connection);
06146   return res;
06147 }
06148 
06159 long
06160 dbus_connection_get_outgoing_size (DBusConnection *connection)
06161 {
06162   long res;
06163 
06164   _dbus_return_val_if_fail (connection != NULL, 0);
06165 
06166   CONNECTION_LOCK (connection);
06167   res = _dbus_counter_get_size_value (connection->outgoing_counter);
06168   CONNECTION_UNLOCK (connection);
06169   return res;
06170 }
06171 
06172 #ifdef DBUS_ENABLE_STATS
06173 void
06174 _dbus_connection_get_stats (DBusConnection *connection,
06175                             dbus_uint32_t  *in_messages,
06176                             dbus_uint32_t  *in_bytes,
06177                             dbus_uint32_t  *in_fds,
06178                             dbus_uint32_t  *in_peak_bytes,
06179                             dbus_uint32_t  *in_peak_fds,
06180                             dbus_uint32_t  *out_messages,
06181                             dbus_uint32_t  *out_bytes,
06182                             dbus_uint32_t  *out_fds,
06183                             dbus_uint32_t  *out_peak_bytes,
06184                             dbus_uint32_t  *out_peak_fds)
06185 {
06186   CONNECTION_LOCK (connection);
06187 
06188   if (in_messages != NULL)
06189     *in_messages = connection->n_incoming;
06190 
06191   _dbus_transport_get_stats (connection->transport,
06192                              in_bytes, in_fds, in_peak_bytes, in_peak_fds);
06193 
06194   if (out_messages != NULL)
06195     *out_messages = connection->n_outgoing;
06196 
06197   if (out_bytes != NULL)
06198     *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
06199 
06200   if (out_fds != NULL)
06201     *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06202 
06203   if (out_peak_bytes != NULL)
06204     *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
06205 
06206   if (out_peak_fds != NULL)
06207     *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
06208 
06209   CONNECTION_UNLOCK (connection);
06210 }
06211 #endif /* DBUS_ENABLE_STATS */
06212 
06220 long
06221 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06222 {
06223   long res;
06224 
06225   _dbus_return_val_if_fail (connection != NULL, 0);
06226 
06227   CONNECTION_LOCK (connection);
06228   res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06229   CONNECTION_UNLOCK (connection);
06230   return res;
06231 }
06232