D-Bus 1.4.12
dbus-connection.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002-2006  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-pending-call-internal.h"
00033 #include "dbus-list.h"
00034 #include "dbus-hash.h"
00035 #include "dbus-message-internal.h"
00036 #include "dbus-message-private.h"
00037 #include "dbus-threads.h"
00038 #include "dbus-protocol.h"
00039 #include "dbus-dataslot.h"
00040 #include "dbus-string.h"
00041 #include "dbus-pending-call.h"
00042 #include "dbus-object-tree.h"
00043 #include "dbus-threads-internal.h"
00044 #include "dbus-bus.h"
00045 #include "dbus-marshal-basic.h"
00046 
00047 #ifdef DBUS_DISABLE_CHECKS
00048 #define TOOK_LOCK_CHECK(connection)
00049 #define RELEASING_LOCK_CHECK(connection)
00050 #define HAVE_LOCK_CHECK(connection)
00051 #else
00052 #define TOOK_LOCK_CHECK(connection) do {                \
00053     _dbus_assert (!(connection)->have_connection_lock); \
00054     (connection)->have_connection_lock = TRUE;          \
00055   } while (0)
00056 #define RELEASING_LOCK_CHECK(connection) do {            \
00057     _dbus_assert ((connection)->have_connection_lock);   \
00058     (connection)->have_connection_lock = FALSE;          \
00059   } while (0)
00060 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00061 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00062 #endif
00063 
00064 #define TRACE_LOCKS 1
00065 
00066 #define CONNECTION_LOCK(connection)   do {                                      \
00067     if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); }   \
00068     _dbus_mutex_lock ((connection)->mutex);                                      \
00069     TOOK_LOCK_CHECK (connection);                                               \
00070   } while (0)
00071 
00072 #define CONNECTION_UNLOCK(connection) do {                                              \
00073     if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n");  }        \
00074     RELEASING_LOCK_CHECK (connection);                                                  \
00075     _dbus_mutex_unlock ((connection)->mutex);                                            \
00076   } while (0)
00077 
00078 #define SLOTS_LOCK(connection) do {                     \
00079     _dbus_mutex_lock ((connection)->slot_mutex);        \
00080   } while (0)
00081 
00082 #define SLOTS_UNLOCK(connection) do {                   \
00083     _dbus_mutex_unlock ((connection)->slot_mutex);      \
00084   } while (0)
00085 
00086 #define DISPATCH_STATUS_NAME(s)                                            \
00087                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00088                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00089                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00090                       "???")
00091 
00212 typedef struct DBusMessageFilter DBusMessageFilter;
00213 
00217 struct DBusMessageFilter
00218 {
00219   DBusAtomic refcount; 
00220   DBusHandleMessageFunction function; 
00221   void *user_data; 
00222   DBusFreeFunction free_user_data_function; 
00223 };
00224 
00225 
00229 struct DBusPreallocatedSend
00230 {
00231   DBusConnection *connection; 
00232   DBusList *queue_link;       
00233   DBusList *counter_link;     
00234 };
00235 
00236 #if HAVE_DECL_MSG_NOSIGNAL
00237 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00238 #else
00239 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00240 #endif
00241 
00245 struct DBusConnection
00246 {
00247   DBusAtomic refcount; 
00249   DBusMutex *mutex; 
00251   DBusMutex *dispatch_mutex;     
00252   DBusCondVar *dispatch_cond;    
00253   DBusMutex *io_path_mutex;      
00254   DBusCondVar *io_path_cond;     
00256   DBusList *outgoing_messages; 
00257   DBusList *incoming_messages; 
00259   DBusMessage *message_borrowed; 
00263   int n_outgoing;              
00264   int n_incoming;              
00266   DBusCounter *outgoing_counter; 
00268   DBusTransport *transport;    
00269   DBusWatchList *watches;      
00270   DBusTimeoutList *timeouts;   
00272   DBusList *filter_list;        
00274   DBusMutex *slot_mutex;        
00275   DBusDataSlotList slot_list;   
00277   DBusHashTable *pending_replies;  
00279   dbus_uint32_t client_serial;       
00280   DBusList *disconnect_message_link; 
00282   DBusWakeupMainFunction wakeup_main_function; 
00283   void *wakeup_main_data; 
00284   DBusFreeFunction free_wakeup_main_data; 
00286   DBusDispatchStatusFunction dispatch_status_function; 
00287   void *dispatch_status_data; 
00288   DBusFreeFunction free_dispatch_status_data; 
00290   DBusDispatchStatus last_dispatch_status; 
00292   DBusList *link_cache; 
00295   DBusObjectTree *objects; 
00297   char *server_guid; 
00299   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00300    * from connection->mutex and all bitfields in a word have to be read/written together.
00301    * So you can't have a different lock for different bitfields in the same word.
00302    */
00303   dbus_bool_t dispatch_acquired; 
00304   dbus_bool_t io_path_acquired;  
00306   unsigned int shareable : 1; 
00308   unsigned int exit_on_disconnect : 1; 
00310   unsigned int route_peer_messages : 1; 
00312   unsigned int disconnected_message_arrived : 1;   
00316   unsigned int disconnected_message_processed : 1; 
00320 #ifndef DBUS_DISABLE_CHECKS
00321   unsigned int have_connection_lock : 1; 
00322 #endif
00323   
00324 #ifndef DBUS_DISABLE_CHECKS
00325   int generation; 
00326 #endif 
00327 };
00328 
00329 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00330 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00331                                                                               DBusDispatchStatus  new_status);
00332 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00333 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00334 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00335 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00336 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00337 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00338 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
00339                                                                               dbus_uint32_t       client_serial);
00340 
00341 static DBusMessageFilter *
00342 _dbus_message_filter_ref (DBusMessageFilter *filter)
00343 {
00344   _dbus_assert (filter->refcount.value > 0);
00345   _dbus_atomic_inc (&filter->refcount);
00346 
00347   return filter;
00348 }
00349 
00350 static void
00351 _dbus_message_filter_unref (DBusMessageFilter *filter)
00352 {
00353   _dbus_assert (filter->refcount.value > 0);
00354 
00355   if (_dbus_atomic_dec (&filter->refcount) == 1)
00356     {
00357       if (filter->free_user_data_function)
00358         (* filter->free_user_data_function) (filter->user_data);
00359       
00360       dbus_free (filter);
00361     }
00362 }
00363 
00369 void
00370 _dbus_connection_lock (DBusConnection *connection)
00371 {
00372   CONNECTION_LOCK (connection);
00373 }
00374 
00380 void
00381 _dbus_connection_unlock (DBusConnection *connection)
00382 {
00383   CONNECTION_UNLOCK (connection);
00384 }
00385 
00393 static void
00394 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00395 {
00396   if (connection->wakeup_main_function)
00397     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00398 }
00399 
00400 #ifdef DBUS_BUILD_TESTS
00401 /* For now this function isn't used */
00411 dbus_bool_t
00412 _dbus_connection_queue_received_message (DBusConnection *connection,
00413                                          DBusMessage    *message)
00414 {
00415   DBusList *link;
00416 
00417   link = _dbus_list_alloc_link (message);
00418   if (link == NULL)
00419     return FALSE;
00420 
00421   dbus_message_ref (message);
00422   _dbus_connection_queue_received_message_link (connection, link);
00423 
00424   return TRUE;
00425 }
00426 
00439 void 
00440 _dbus_connection_test_get_locks (DBusConnection *connection,
00441                                  DBusMutex     **mutex_loc,
00442                                  DBusMutex     **dispatch_mutex_loc,
00443                                  DBusMutex     **io_path_mutex_loc,
00444                                  DBusCondVar   **dispatch_cond_loc,
00445                                  DBusCondVar   **io_path_cond_loc)
00446 {
00447   *mutex_loc = connection->mutex;
00448   *dispatch_mutex_loc = connection->dispatch_mutex;
00449   *io_path_mutex_loc = connection->io_path_mutex; 
00450   *dispatch_cond_loc = connection->dispatch_cond;
00451   *io_path_cond_loc = connection->io_path_cond;
00452 }
00453 #endif
00454 
00463 void
00464 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00465                                               DBusList        *link)
00466 {
00467   DBusPendingCall *pending;
00468   dbus_uint32_t reply_serial;
00469   DBusMessage *message;
00470   
00471   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00472   
00473   _dbus_list_append_link (&connection->incoming_messages,
00474                           link);
00475   message = link->data;
00476 
00477   /* If this is a reply we're waiting on, remove timeout for it */
00478   reply_serial = dbus_message_get_reply_serial (message);
00479   if (reply_serial != 0)
00480     {
00481       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00482                                              reply_serial);
00483       if (pending != NULL)
00484         {
00485           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00486             _dbus_connection_remove_timeout_unlocked (connection,
00487                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00488 
00489           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00490         }
00491     }
00492   
00493   
00494 
00495   connection->n_incoming += 1;
00496 
00497   _dbus_connection_wakeup_mainloop (connection);
00498   
00499   _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00500                  message,
00501                  dbus_message_type_to_string (dbus_message_get_type (message)),
00502                  dbus_message_get_path (message) ?
00503                  dbus_message_get_path (message) :
00504                  "no path",
00505                  dbus_message_get_interface (message) ?
00506                  dbus_message_get_interface (message) :
00507                  "no interface",
00508                  dbus_message_get_member (message) ?
00509                  dbus_message_get_member (message) :
00510                  "no member",
00511                  dbus_message_get_signature (message),
00512                  dbus_message_get_reply_serial (message),
00513                  connection,
00514                  connection->n_incoming);}
00515 
00524 void
00525 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00526                                                  DBusList *link)
00527 {
00528   HAVE_LOCK_CHECK (connection);
00529   
00530   _dbus_list_append_link (&connection->incoming_messages, link);
00531 
00532   connection->n_incoming += 1;
00533 
00534   _dbus_connection_wakeup_mainloop (connection);
00535   
00536   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00537                  link->data, connection, connection->n_incoming);
00538 }
00539 
00540 
00548 dbus_bool_t
00549 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00550 {
00551   HAVE_LOCK_CHECK (connection);
00552   return connection->outgoing_messages != NULL;
00553 }
00554 
00564 dbus_bool_t
00565 dbus_connection_has_messages_to_send (DBusConnection *connection)
00566 {
00567   dbus_bool_t v;
00568   
00569   _dbus_return_val_if_fail (connection != NULL, FALSE);
00570 
00571   CONNECTION_LOCK (connection);
00572   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00573   CONNECTION_UNLOCK (connection);
00574 
00575   return v;
00576 }
00577 
00585 DBusMessage*
00586 _dbus_connection_get_message_to_send (DBusConnection *connection)
00587 {
00588   HAVE_LOCK_CHECK (connection);
00589   
00590   return _dbus_list_get_last (&connection->outgoing_messages);
00591 }
00592 
00601 void
00602 _dbus_connection_message_sent (DBusConnection *connection,
00603                                DBusMessage    *message)
00604 {
00605   DBusList *link;
00606 
00607   HAVE_LOCK_CHECK (connection);
00608   
00609   /* This can be called before we even complete authentication, since
00610    * it's called on disconnect to clean up the outgoing queue.
00611    * It's also called as we successfully send each message.
00612    */
00613   
00614   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00615   _dbus_assert (link != NULL);
00616   _dbus_assert (link->data == message);
00617 
00618   /* Save this link in the link cache */
00619   _dbus_list_unlink (&connection->outgoing_messages,
00620                      link);
00621   _dbus_list_prepend_link (&connection->link_cache, link);
00622   
00623   connection->n_outgoing -= 1;
00624 
00625   _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00626                  message,
00627                  dbus_message_type_to_string (dbus_message_get_type (message)),
00628                  dbus_message_get_path (message) ?
00629                  dbus_message_get_path (message) :
00630                  "no path",
00631                  dbus_message_get_interface (message) ?
00632                  dbus_message_get_interface (message) :
00633                  "no interface",
00634                  dbus_message_get_member (message) ?
00635                  dbus_message_get_member (message) :
00636                  "no member",
00637                  dbus_message_get_signature (message),
00638                  connection, connection->n_outgoing);
00639 
00640   /* Save this link in the link cache also */
00641   _dbus_message_remove_counter (message, connection->outgoing_counter,
00642                                 &link);
00643   _dbus_list_prepend_link (&connection->link_cache, link);
00644   
00645   dbus_message_unref (message);
00646 }
00647 
00649 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00650                                                   DBusWatch     *watch);
00652 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00653                                                   DBusWatch     *watch);
00655 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00656                                                   DBusWatch     *watch,
00657                                                   dbus_bool_t    enabled);
00658 
00659 static dbus_bool_t
00660 protected_change_watch (DBusConnection         *connection,
00661                         DBusWatch              *watch,
00662                         DBusWatchAddFunction    add_function,
00663                         DBusWatchRemoveFunction remove_function,
00664                         DBusWatchToggleFunction toggle_function,
00665                         dbus_bool_t             enabled)
00666 {
00667   dbus_bool_t retval;
00668 
00669   HAVE_LOCK_CHECK (connection);
00670 
00671   /* The original purpose of protected_change_watch() was to hold a
00672    * ref on the connection while dropping the connection lock, then
00673    * calling out to the app.  This was a broken hack that did not
00674    * work, since the connection was in a hosed state (no WatchList
00675    * field) while calling out.
00676    *
00677    * So for now we'll just keep the lock while calling out. This means
00678    * apps are not allowed to call DBusConnection methods inside a
00679    * watch function or they will deadlock.
00680    *
00681    * The "real fix" is to use the _and_unlock() pattern found
00682    * elsewhere in the code, to defer calling out to the app until
00683    * we're about to drop locks and return flow of control to the app
00684    * anyway.
00685    *
00686    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00687    */
00688 
00689   if (connection->watches)
00690     {
00691       if (add_function)
00692         retval = (* add_function) (connection->watches, watch);
00693       else if (remove_function)
00694         {
00695           retval = TRUE;
00696           (* remove_function) (connection->watches, watch);
00697         }
00698       else
00699         {
00700           retval = TRUE;
00701           (* toggle_function) (connection->watches, watch, enabled);
00702         }
00703       return retval;
00704     }
00705   else
00706     return FALSE;
00707 }
00708      
00709 
00721 dbus_bool_t
00722 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00723                                      DBusWatch      *watch)
00724 {
00725   return protected_change_watch (connection, watch,
00726                                  _dbus_watch_list_add_watch,
00727                                  NULL, NULL, FALSE);
00728 }
00729 
00739 void
00740 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00741                                         DBusWatch      *watch)
00742 {
00743   protected_change_watch (connection, watch,
00744                           NULL,
00745                           _dbus_watch_list_remove_watch,
00746                           NULL, FALSE);
00747 }
00748 
00759 void
00760 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00761                                         DBusWatch      *watch,
00762                                         dbus_bool_t     enabled)
00763 {
00764   _dbus_assert (watch != NULL);
00765 
00766   protected_change_watch (connection, watch,
00767                           NULL, NULL,
00768                           _dbus_watch_list_toggle_watch,
00769                           enabled);
00770 }
00771 
00773 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00774                                                    DBusTimeout     *timeout);
00776 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00777                                                    DBusTimeout     *timeout);
00779 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00780                                                    DBusTimeout     *timeout,
00781                                                    dbus_bool_t      enabled);
00782 
00783 static dbus_bool_t
00784 protected_change_timeout (DBusConnection           *connection,
00785                           DBusTimeout              *timeout,
00786                           DBusTimeoutAddFunction    add_function,
00787                           DBusTimeoutRemoveFunction remove_function,
00788                           DBusTimeoutToggleFunction toggle_function,
00789                           dbus_bool_t               enabled)
00790 {
00791   dbus_bool_t retval;
00792 
00793   HAVE_LOCK_CHECK (connection);
00794 
00795   /* The original purpose of protected_change_timeout() was to hold a
00796    * ref on the connection while dropping the connection lock, then
00797    * calling out to the app.  This was a broken hack that did not
00798    * work, since the connection was in a hosed state (no TimeoutList
00799    * field) while calling out.
00800    *
00801    * So for now we'll just keep the lock while calling out. This means
00802    * apps are not allowed to call DBusConnection methods inside a
00803    * timeout function or they will deadlock.
00804    *
00805    * The "real fix" is to use the _and_unlock() pattern found
00806    * elsewhere in the code, to defer calling out to the app until
00807    * we're about to drop locks and return flow of control to the app
00808    * anyway.
00809    *
00810    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00811    */
00812 
00813   if (connection->timeouts)
00814     {
00815       if (add_function)
00816         retval = (* add_function) (connection->timeouts, timeout);
00817       else if (remove_function)
00818         {
00819           retval = TRUE;
00820           (* remove_function) (connection->timeouts, timeout);
00821         }
00822       else
00823         {
00824           retval = TRUE;
00825           (* toggle_function) (connection->timeouts, timeout, enabled);
00826         }
00827       return retval;
00828     }
00829   else
00830     return FALSE;
00831 }
00832 
00845 dbus_bool_t
00846 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00847                                        DBusTimeout    *timeout)
00848 {
00849   return protected_change_timeout (connection, timeout,
00850                                    _dbus_timeout_list_add_timeout,
00851                                    NULL, NULL, FALSE);
00852 }
00853 
00863 void
00864 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00865                                           DBusTimeout    *timeout)
00866 {
00867   protected_change_timeout (connection, timeout,
00868                             NULL,
00869                             _dbus_timeout_list_remove_timeout,
00870                             NULL, FALSE);
00871 }
00872 
00883 void
00884 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00885                                           DBusTimeout      *timeout,
00886                                           dbus_bool_t       enabled)
00887 {
00888   protected_change_timeout (connection, timeout,
00889                             NULL, NULL,
00890                             _dbus_timeout_list_toggle_timeout,
00891                             enabled);
00892 }
00893 
00894 static dbus_bool_t
00895 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00896                                                DBusPendingCall *pending)
00897 {
00898   dbus_uint32_t reply_serial;
00899   DBusTimeout *timeout;
00900 
00901   HAVE_LOCK_CHECK (connection);
00902 
00903   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00904 
00905   _dbus_assert (reply_serial != 0);
00906 
00907   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00908 
00909   if (timeout)
00910     {
00911       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00912         return FALSE;
00913       
00914       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00915                                         reply_serial,
00916                                         pending))
00917         {
00918           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00919 
00920           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00921           HAVE_LOCK_CHECK (connection);
00922           return FALSE;
00923         }
00924       
00925       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00926     }
00927   else
00928     {
00929       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00930                                         reply_serial,
00931                                         pending))
00932         {
00933           HAVE_LOCK_CHECK (connection);
00934           return FALSE;
00935         }
00936     }
00937 
00938   _dbus_pending_call_ref_unlocked (pending);
00939 
00940   HAVE_LOCK_CHECK (connection);
00941   
00942   return TRUE;
00943 }
00944 
00945 static void
00946 free_pending_call_on_hash_removal (void *data)
00947 {
00948   DBusPendingCall *pending;
00949   DBusConnection  *connection;
00950   
00951   if (data == NULL)
00952     return;
00953 
00954   pending = data;
00955 
00956   connection = _dbus_pending_call_get_connection_unlocked (pending);
00957 
00958   HAVE_LOCK_CHECK (connection);
00959   
00960   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00961     {
00962       _dbus_connection_remove_timeout_unlocked (connection,
00963                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00964       
00965       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00966     }
00967 
00968   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00969    * here, but the pending call finalizer could in principle call out to 
00970    * application code so we pretty much have to... some larger code reorg 
00971    * might be needed.
00972    */
00973   _dbus_connection_ref_unlocked (connection);
00974   _dbus_pending_call_unref_and_unlock (pending);
00975   CONNECTION_LOCK (connection);
00976   _dbus_connection_unref_unlocked (connection);
00977 }
00978 
00979 static void
00980 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00981                                                DBusPendingCall *pending)
00982 {
00983   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00984    * say the least.
00985    */
00986   _dbus_hash_table_remove_int (connection->pending_replies,
00987                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00988 }
00989 
00990 static void
00991 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00992                                                  DBusPendingCall *pending)
00993 {
00994   /* The idea here is to avoid finalizing the pending call
00995    * with the lock held, since there's a destroy notifier
00996    * in pending call that goes out to application code.
00997    *
00998    * There's an extra unlock inside the hash table
00999    * "free pending call" function FIXME...
01000    */
01001   _dbus_pending_call_ref_unlocked (pending);
01002   _dbus_hash_table_remove_int (connection->pending_replies,
01003                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01004 
01005   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01006       _dbus_connection_remove_timeout_unlocked (connection,
01007               _dbus_pending_call_get_timeout_unlocked (pending));
01008 
01009   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01010 
01011   _dbus_pending_call_unref_and_unlock (pending);
01012 }
01013 
01022 void
01023 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01024                                       DBusPendingCall *pending)
01025 {
01026   CONNECTION_LOCK (connection);
01027   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01028 }
01029 
01039 static dbus_bool_t
01040 _dbus_connection_acquire_io_path (DBusConnection *connection,
01041                                   int             timeout_milliseconds)
01042 {
01043   dbus_bool_t we_acquired;
01044   
01045   HAVE_LOCK_CHECK (connection);
01046 
01047   /* We don't want the connection to vanish */
01048   _dbus_connection_ref_unlocked (connection);
01049 
01050   /* We will only touch io_path_acquired which is protected by our mutex */
01051   CONNECTION_UNLOCK (connection);
01052   
01053   _dbus_verbose ("locking io_path_mutex\n");
01054   _dbus_mutex_lock (connection->io_path_mutex);
01055 
01056   _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01057                  connection->io_path_acquired, timeout_milliseconds);
01058 
01059   we_acquired = FALSE;
01060   
01061   if (connection->io_path_acquired)
01062     {
01063       if (timeout_milliseconds != -1)
01064         {
01065           _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01066                          timeout_milliseconds);
01067 
01068           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01069                                            connection->io_path_mutex,
01070                                            timeout_milliseconds))
01071             {
01072               /* We timed out before anyone signaled. */
01073               /* (writing the loop to handle the !timedout case by
01074                * waiting longer if needed is a pain since dbus
01075                * wraps pthread_cond_timedwait to take a relative
01076                * time instead of absolute, something kind of stupid
01077                * on our part. for now it doesn't matter, we will just
01078                * end up back here eventually.)
01079                */
01080             }
01081         }
01082       else
01083         {
01084           while (connection->io_path_acquired)
01085             {
01086               _dbus_verbose ("waiting for IO path to be acquirable\n");
01087               _dbus_condvar_wait (connection->io_path_cond, 
01088                                   connection->io_path_mutex);
01089             }
01090         }
01091     }
01092   
01093   if (!connection->io_path_acquired)
01094     {
01095       we_acquired = TRUE;
01096       connection->io_path_acquired = TRUE;
01097     }
01098   
01099   _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01100                  connection->io_path_acquired, we_acquired);
01101 
01102   _dbus_verbose ("unlocking io_path_mutex\n");
01103   _dbus_mutex_unlock (connection->io_path_mutex);
01104 
01105   CONNECTION_LOCK (connection);
01106   
01107   HAVE_LOCK_CHECK (connection);
01108 
01109   _dbus_connection_unref_unlocked (connection);
01110   
01111   return we_acquired;
01112 }
01113 
01121 static void
01122 _dbus_connection_release_io_path (DBusConnection *connection)
01123 {
01124   HAVE_LOCK_CHECK (connection);
01125   
01126   _dbus_verbose ("locking io_path_mutex\n");
01127   _dbus_mutex_lock (connection->io_path_mutex);
01128   
01129   _dbus_assert (connection->io_path_acquired);
01130 
01131   _dbus_verbose ("start connection->io_path_acquired = %d\n",
01132                  connection->io_path_acquired);
01133   
01134   connection->io_path_acquired = FALSE;
01135   _dbus_condvar_wake_one (connection->io_path_cond);
01136 
01137   _dbus_verbose ("unlocking io_path_mutex\n");
01138   _dbus_mutex_unlock (connection->io_path_mutex);
01139 }
01140 
01176 void
01177 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01178                                         DBusPendingCall *pending,
01179                                         unsigned int    flags,
01180                                         int             timeout_milliseconds)
01181 {
01182   _dbus_verbose ("start\n");
01183   
01184   HAVE_LOCK_CHECK (connection);
01185   
01186   if (connection->n_outgoing == 0)
01187     flags &= ~DBUS_ITERATION_DO_WRITING;
01188 
01189   if (_dbus_connection_acquire_io_path (connection,
01190                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01191     {
01192       HAVE_LOCK_CHECK (connection);
01193       
01194       if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01195         {
01196           _dbus_verbose ("pending call completed while acquiring I/O path");
01197         }
01198       else if ( (pending != NULL) &&
01199                 _dbus_connection_peek_for_reply_unlocked (connection,
01200                                                           _dbus_pending_call_get_reply_serial_unlocked (pending)))
01201         {
01202           _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01203         }
01204       else
01205         {
01206           _dbus_transport_do_iteration (connection->transport,
01207                                         flags, timeout_milliseconds);
01208         }
01209 
01210       _dbus_connection_release_io_path (connection);
01211     }
01212 
01213   HAVE_LOCK_CHECK (connection);
01214 
01215   _dbus_verbose ("end\n");
01216 }
01217 
01227 DBusConnection*
01228 _dbus_connection_new_for_transport (DBusTransport *transport)
01229 {
01230   DBusConnection *connection;
01231   DBusWatchList *watch_list;
01232   DBusTimeoutList *timeout_list;
01233   DBusHashTable *pending_replies;
01234   DBusList *disconnect_link;
01235   DBusMessage *disconnect_message;
01236   DBusCounter *outgoing_counter;
01237   DBusObjectTree *objects;
01238   
01239   watch_list = NULL;
01240   connection = NULL;
01241   pending_replies = NULL;
01242   timeout_list = NULL;
01243   disconnect_link = NULL;
01244   disconnect_message = NULL;
01245   outgoing_counter = NULL;
01246   objects = NULL;
01247   
01248   watch_list = _dbus_watch_list_new ();
01249   if (watch_list == NULL)
01250     goto error;
01251 
01252   timeout_list = _dbus_timeout_list_new ();
01253   if (timeout_list == NULL)
01254     goto error;  
01255 
01256   pending_replies =
01257     _dbus_hash_table_new (DBUS_HASH_INT,
01258                           NULL,
01259                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01260   if (pending_replies == NULL)
01261     goto error;
01262   
01263   connection = dbus_new0 (DBusConnection, 1);
01264   if (connection == NULL)
01265     goto error;
01266 
01267   _dbus_mutex_new_at_location (&connection->mutex);
01268   if (connection->mutex == NULL)
01269     goto error;
01270 
01271   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01272   if (connection->io_path_mutex == NULL)
01273     goto error;
01274 
01275   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01276   if (connection->dispatch_mutex == NULL)
01277     goto error;
01278   
01279   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01280   if (connection->dispatch_cond == NULL)
01281     goto error;
01282   
01283   _dbus_condvar_new_at_location (&connection->io_path_cond);
01284   if (connection->io_path_cond == NULL)
01285     goto error;
01286 
01287   _dbus_mutex_new_at_location (&connection->slot_mutex);
01288   if (connection->slot_mutex == NULL)
01289     goto error;
01290 
01291   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01292                                                 DBUS_INTERFACE_LOCAL,
01293                                                 "Disconnected");
01294   
01295   if (disconnect_message == NULL)
01296     goto error;
01297 
01298   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01299   if (disconnect_link == NULL)
01300     goto error;
01301 
01302   outgoing_counter = _dbus_counter_new ();
01303   if (outgoing_counter == NULL)
01304     goto error;
01305 
01306   objects = _dbus_object_tree_new (connection);
01307   if (objects == NULL)
01308     goto error;
01309   
01310   if (_dbus_modify_sigpipe)
01311     _dbus_disable_sigpipe ();
01312   
01313   connection->refcount.value = 1;
01314   connection->transport = transport;
01315   connection->watches = watch_list;
01316   connection->timeouts = timeout_list;
01317   connection->pending_replies = pending_replies;
01318   connection->outgoing_counter = outgoing_counter;
01319   connection->filter_list = NULL;
01320   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01321   connection->objects = objects;
01322   connection->exit_on_disconnect = FALSE;
01323   connection->shareable = FALSE;
01324   connection->route_peer_messages = FALSE;
01325   connection->disconnected_message_arrived = FALSE;
01326   connection->disconnected_message_processed = FALSE;
01327   
01328 #ifndef DBUS_DISABLE_CHECKS
01329   connection->generation = _dbus_current_generation;
01330 #endif
01331   
01332   _dbus_data_slot_list_init (&connection->slot_list);
01333 
01334   connection->client_serial = 1;
01335 
01336   connection->disconnect_message_link = disconnect_link;
01337 
01338   CONNECTION_LOCK (connection);
01339   
01340   if (!_dbus_transport_set_connection (transport, connection))
01341     {
01342       CONNECTION_UNLOCK (connection);
01343 
01344       goto error;
01345     }
01346 
01347   _dbus_transport_ref (transport);
01348 
01349   CONNECTION_UNLOCK (connection);
01350   
01351   return connection;
01352   
01353  error:
01354   if (disconnect_message != NULL)
01355     dbus_message_unref (disconnect_message);
01356   
01357   if (disconnect_link != NULL)
01358     _dbus_list_free_link (disconnect_link);
01359   
01360   if (connection != NULL)
01361     {
01362       _dbus_condvar_free_at_location (&connection->io_path_cond);
01363       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01364       _dbus_mutex_free_at_location (&connection->mutex);
01365       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01366       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01367       _dbus_mutex_free_at_location (&connection->slot_mutex);
01368       dbus_free (connection);
01369     }
01370   if (pending_replies)
01371     _dbus_hash_table_unref (pending_replies);
01372   
01373   if (watch_list)
01374     _dbus_watch_list_free (watch_list);
01375 
01376   if (timeout_list)
01377     _dbus_timeout_list_free (timeout_list);
01378 
01379   if (outgoing_counter)
01380     _dbus_counter_unref (outgoing_counter);
01381 
01382   if (objects)
01383     _dbus_object_tree_unref (objects);
01384   
01385   return NULL;
01386 }
01387 
01395 DBusConnection *
01396 _dbus_connection_ref_unlocked (DBusConnection *connection)
01397 {  
01398   _dbus_assert (connection != NULL);
01399   _dbus_assert (connection->generation == _dbus_current_generation);
01400 
01401   HAVE_LOCK_CHECK (connection);
01402 
01403   _dbus_atomic_inc (&connection->refcount);
01404 
01405   return connection;
01406 }
01407 
01414 void
01415 _dbus_connection_unref_unlocked (DBusConnection *connection)
01416 {
01417   dbus_bool_t last_unref;
01418 
01419   HAVE_LOCK_CHECK (connection);
01420   
01421   _dbus_assert (connection != NULL);
01422 
01423   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01424 
01425   if (last_unref)
01426     _dbus_connection_last_unref (connection);
01427 }
01428 
01429 static dbus_uint32_t
01430 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01431 {
01432   dbus_uint32_t serial;
01433 
01434   serial = connection->client_serial++;
01435 
01436   if (connection->client_serial == 0)
01437     connection->client_serial = 1;
01438 
01439   return serial;
01440 }
01441 
01455 dbus_bool_t
01456 _dbus_connection_handle_watch (DBusWatch                   *watch,
01457                                unsigned int                 condition,
01458                                void                        *data)
01459 {
01460   DBusConnection *connection;
01461   dbus_bool_t retval;
01462   DBusDispatchStatus status;
01463 
01464   connection = data;
01465 
01466   _dbus_verbose ("start\n");
01467   
01468   CONNECTION_LOCK (connection);
01469 
01470   if (!_dbus_connection_acquire_io_path (connection, 1))
01471     {
01472       /* another thread is handling the message */
01473       CONNECTION_UNLOCK (connection);
01474       return TRUE;
01475     }
01476 
01477   HAVE_LOCK_CHECK (connection);
01478   retval = _dbus_transport_handle_watch (connection->transport,
01479                                          watch, condition);
01480 
01481   _dbus_connection_release_io_path (connection);
01482 
01483   HAVE_LOCK_CHECK (connection);
01484 
01485   _dbus_verbose ("middle\n");
01486   
01487   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01488 
01489   /* this calls out to user code */
01490   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01491 
01492   _dbus_verbose ("end\n");
01493   
01494   return retval;
01495 }
01496 
01497 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01498 static DBusHashTable *shared_connections = NULL;
01499 static DBusList *shared_connections_no_guid = NULL;
01500 
01501 static void
01502 close_connection_on_shutdown (DBusConnection *connection)
01503 {
01504   DBusMessage *message;
01505 
01506   dbus_connection_ref (connection);
01507   _dbus_connection_close_possibly_shared (connection);
01508 
01509   /* Churn through to the Disconnected message */
01510   while ((message = dbus_connection_pop_message (connection)))
01511     {
01512       dbus_message_unref (message);
01513     }
01514   dbus_connection_unref (connection);
01515 }
01516 
01517 static void
01518 shared_connections_shutdown (void *data)
01519 {
01520   int n_entries;
01521   
01522   _DBUS_LOCK (shared_connections);
01523   
01524   /* This is a little bit unpleasant... better ideas? */
01525   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01526     {
01527       DBusConnection *connection;
01528       DBusHashIter iter;
01529       
01530       _dbus_hash_iter_init (shared_connections, &iter);
01531       _dbus_hash_iter_next (&iter);
01532        
01533       connection = _dbus_hash_iter_get_value (&iter);
01534 
01535       _DBUS_UNLOCK (shared_connections);
01536       close_connection_on_shutdown (connection);
01537       _DBUS_LOCK (shared_connections);
01538 
01539       /* The connection should now be dead and not in our hash ... */
01540       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01541     }
01542 
01543   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01544   
01545   _dbus_hash_table_unref (shared_connections);
01546   shared_connections = NULL;
01547 
01548   if (shared_connections_no_guid != NULL)
01549     {
01550       DBusConnection *connection;
01551       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01552       while (connection != NULL)
01553         {
01554           _DBUS_UNLOCK (shared_connections);
01555           close_connection_on_shutdown (connection);
01556           _DBUS_LOCK (shared_connections);
01557           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01558         }
01559     }
01560 
01561   shared_connections_no_guid = NULL;
01562   
01563   _DBUS_UNLOCK (shared_connections);
01564 }
01565 
01566 static dbus_bool_t
01567 connection_lookup_shared (DBusAddressEntry  *entry,
01568                           DBusConnection   **result)
01569 {
01570   _dbus_verbose ("checking for existing connection\n");
01571   
01572   *result = NULL;
01573   
01574   _DBUS_LOCK (shared_connections);
01575 
01576   if (shared_connections == NULL)
01577     {
01578       _dbus_verbose ("creating shared_connections hash table\n");
01579       
01580       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01581                                                  dbus_free,
01582                                                  NULL);
01583       if (shared_connections == NULL)
01584         {
01585           _DBUS_UNLOCK (shared_connections);
01586           return FALSE;
01587         }
01588 
01589       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01590         {
01591           _dbus_hash_table_unref (shared_connections);
01592           shared_connections = NULL;
01593           _DBUS_UNLOCK (shared_connections);
01594           return FALSE;
01595         }
01596 
01597       _dbus_verbose ("  successfully created shared_connections\n");
01598       
01599       _DBUS_UNLOCK (shared_connections);
01600       return TRUE; /* no point looking up in the hash we just made */
01601     }
01602   else
01603     {
01604       const char *guid;
01605 
01606       guid = dbus_address_entry_get_value (entry, "guid");
01607       
01608       if (guid != NULL)
01609         {
01610           DBusConnection *connection;
01611           
01612           connection = _dbus_hash_table_lookup_string (shared_connections,
01613                                                        guid);
01614 
01615           if (connection)
01616             {
01617               /* The DBusConnection can't be finalized without taking
01618                * the shared_connections lock to remove it from the
01619                * hash.  So it's safe to ref the connection here.
01620                * However, it may be disconnected if the Disconnected
01621                * message hasn't been processed yet, in which case we
01622                * want to pretend it isn't in the hash and avoid
01623                * returning it.
01624                *
01625                * The idea is to avoid ever returning a disconnected connection
01626                * from dbus_connection_open(). We could just synchronously
01627                * drop our shared ref to the connection on connection disconnect,
01628                * and then assert here that the connection is connected, but
01629                * that causes reentrancy headaches.
01630                */
01631               CONNECTION_LOCK (connection);
01632               if (_dbus_connection_get_is_connected_unlocked (connection))
01633                 {
01634                   _dbus_connection_ref_unlocked (connection);
01635                   *result = connection;
01636                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01637                                  guid);
01638                 }
01639               else
01640                 {
01641                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01642                                  guid);
01643                 }
01644               CONNECTION_UNLOCK (connection);
01645             }
01646         }
01647       
01648       _DBUS_UNLOCK (shared_connections);
01649       return TRUE;
01650     }
01651 }
01652 
01653 static dbus_bool_t
01654 connection_record_shared_unlocked (DBusConnection *connection,
01655                                    const char     *guid)
01656 {
01657   char *guid_key;
01658   char *guid_in_connection;
01659 
01660   HAVE_LOCK_CHECK (connection);
01661   _dbus_assert (connection->server_guid == NULL);
01662   _dbus_assert (connection->shareable);
01663 
01664   /* get a hard ref on this connection, even if
01665    * we won't in fact store it in the hash, we still
01666    * need to hold a ref on it until it's disconnected.
01667    */
01668   _dbus_connection_ref_unlocked (connection);
01669 
01670   if (guid == NULL)
01671     {
01672       _DBUS_LOCK (shared_connections);
01673 
01674       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01675         {
01676           _DBUS_UNLOCK (shared_connections);
01677           return FALSE;
01678         }
01679 
01680       _DBUS_UNLOCK (shared_connections);
01681       return TRUE; /* don't store in the hash */
01682     }
01683   
01684   /* A separate copy of the key is required in the hash table, because
01685    * we don't have a lock on the connection when we are doing a hash
01686    * lookup.
01687    */
01688   
01689   guid_key = _dbus_strdup (guid);
01690   if (guid_key == NULL)
01691     return FALSE;
01692 
01693   guid_in_connection = _dbus_strdup (guid);
01694   if (guid_in_connection == NULL)
01695     {
01696       dbus_free (guid_key);
01697       return FALSE;
01698     }
01699   
01700   _DBUS_LOCK (shared_connections);
01701   _dbus_assert (shared_connections != NULL);
01702   
01703   if (!_dbus_hash_table_insert_string (shared_connections,
01704                                        guid_key, connection))
01705     {
01706       dbus_free (guid_key);
01707       dbus_free (guid_in_connection);
01708       _DBUS_UNLOCK (shared_connections);
01709       return FALSE;
01710     }
01711 
01712   connection->server_guid = guid_in_connection;
01713 
01714   _dbus_verbose ("stored connection to %s to be shared\n",
01715                  connection->server_guid);
01716   
01717   _DBUS_UNLOCK (shared_connections);
01718 
01719   _dbus_assert (connection->server_guid != NULL);
01720   
01721   return TRUE;
01722 }
01723 
01724 static void
01725 connection_forget_shared_unlocked (DBusConnection *connection)
01726 {
01727   HAVE_LOCK_CHECK (connection);
01728 
01729   if (!connection->shareable)
01730     return;
01731   
01732   _DBUS_LOCK (shared_connections);
01733       
01734   if (connection->server_guid != NULL)
01735     {
01736       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01737                      connection->server_guid);
01738       
01739       if (!_dbus_hash_table_remove_string (shared_connections,
01740                                            connection->server_guid))
01741         _dbus_assert_not_reached ("connection was not in the shared table");
01742       
01743       dbus_free (connection->server_guid);
01744       connection->server_guid = NULL;
01745     }
01746   else
01747     {
01748       _dbus_list_remove (&shared_connections_no_guid, connection);
01749     }
01750 
01751   _DBUS_UNLOCK (shared_connections);
01752   
01753   /* remove our reference held on all shareable connections */
01754   _dbus_connection_unref_unlocked (connection);
01755 }
01756 
01757 static DBusConnection*
01758 connection_try_from_address_entry (DBusAddressEntry *entry,
01759                                    DBusError        *error)
01760 {
01761   DBusTransport *transport;
01762   DBusConnection *connection;
01763 
01764   transport = _dbus_transport_open (entry, error);
01765 
01766   if (transport == NULL)
01767     {
01768       _DBUS_ASSERT_ERROR_IS_SET (error);
01769       return NULL;
01770     }
01771 
01772   connection = _dbus_connection_new_for_transport (transport);
01773 
01774   _dbus_transport_unref (transport);
01775   
01776   if (connection == NULL)
01777     {
01778       _DBUS_SET_OOM (error);
01779       return NULL;
01780     }
01781 
01782 #ifndef DBUS_DISABLE_CHECKS
01783   _dbus_assert (!connection->have_connection_lock);
01784 #endif
01785   return connection;
01786 }
01787 
01788 /*
01789  * If the shared parameter is true, then any existing connection will
01790  * be used (and if a new connection is created, it will be available
01791  * for use by others). If the shared parameter is false, a new
01792  * connection will always be created, and the new connection will
01793  * never be returned to other callers.
01794  *
01795  * @param address the address
01796  * @param shared whether the connection is shared or private
01797  * @param error error return
01798  * @returns the connection or #NULL on error
01799  */
01800 static DBusConnection*
01801 _dbus_connection_open_internal (const char     *address,
01802                                 dbus_bool_t     shared,
01803                                 DBusError      *error)
01804 {
01805   DBusConnection *connection;
01806   DBusAddressEntry **entries;
01807   DBusError tmp_error = DBUS_ERROR_INIT;
01808   DBusError first_error = DBUS_ERROR_INIT;
01809   int len, i;
01810 
01811   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01812 
01813   _dbus_verbose ("opening %s connection to: %s\n",
01814                  shared ? "shared" : "private", address);
01815   
01816   if (!dbus_parse_address (address, &entries, &len, error))
01817     return NULL;
01818 
01819   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01820   
01821   connection = NULL;
01822 
01823   for (i = 0; i < len; i++)
01824     {
01825       if (shared)
01826         {
01827           if (!connection_lookup_shared (entries[i], &connection))
01828             _DBUS_SET_OOM (&tmp_error);
01829         }
01830 
01831       if (connection == NULL)
01832         {
01833           connection = connection_try_from_address_entry (entries[i],
01834                                                           &tmp_error);
01835 
01836           if (connection != NULL && shared)
01837             {
01838               const char *guid;
01839                   
01840               connection->shareable = TRUE;
01841                   
01842               /* guid may be NULL */
01843               guid = dbus_address_entry_get_value (entries[i], "guid");
01844                   
01845               CONNECTION_LOCK (connection);
01846           
01847               if (!connection_record_shared_unlocked (connection, guid))
01848                 {
01849                   _DBUS_SET_OOM (&tmp_error);
01850                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01851                   dbus_connection_unref (connection);
01852                   connection = NULL;
01853                 }
01854               else
01855                 CONNECTION_UNLOCK (connection);
01856             }
01857         }
01858       
01859       if (connection)
01860         break;
01861 
01862       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01863       
01864       if (i == 0)
01865         dbus_move_error (&tmp_error, &first_error);
01866       else
01867         dbus_error_free (&tmp_error);
01868     }
01869   
01870   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01871   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01872   
01873   if (connection == NULL)
01874     {
01875       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01876       dbus_move_error (&first_error, error);
01877     }
01878   else
01879     dbus_error_free (&first_error);
01880   
01881   dbus_address_entries_free (entries);
01882   return connection;
01883 }
01884 
01893 void
01894 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01895 {
01896   _dbus_assert (connection != NULL);
01897   _dbus_assert (connection->generation == _dbus_current_generation);
01898 
01899   CONNECTION_LOCK (connection);
01900   _dbus_connection_close_possibly_shared_and_unlock (connection);
01901 }
01902 
01903 static DBusPreallocatedSend*
01904 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01905 {
01906   DBusPreallocatedSend *preallocated;
01907 
01908   HAVE_LOCK_CHECK (connection);
01909   
01910   _dbus_assert (connection != NULL);
01911   
01912   preallocated = dbus_new (DBusPreallocatedSend, 1);
01913   if (preallocated == NULL)
01914     return NULL;
01915 
01916   if (connection->link_cache != NULL)
01917     {
01918       preallocated->queue_link =
01919         _dbus_list_pop_first_link (&connection->link_cache);
01920       preallocated->queue_link->data = NULL;
01921     }
01922   else
01923     {
01924       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01925       if (preallocated->queue_link == NULL)
01926         goto failed_0;
01927     }
01928   
01929   if (connection->link_cache != NULL)
01930     {
01931       preallocated->counter_link =
01932         _dbus_list_pop_first_link (&connection->link_cache);
01933       preallocated->counter_link->data = connection->outgoing_counter;
01934     }
01935   else
01936     {
01937       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01938       if (preallocated->counter_link == NULL)
01939         goto failed_1;
01940     }
01941 
01942   _dbus_counter_ref (preallocated->counter_link->data);
01943 
01944   preallocated->connection = connection;
01945   
01946   return preallocated;
01947   
01948  failed_1:
01949   _dbus_list_free_link (preallocated->queue_link);
01950  failed_0:
01951   dbus_free (preallocated);
01952   
01953   return NULL;
01954 }
01955 
01956 /* Called with lock held, does not update dispatch status */
01957 static void
01958 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01959                                                        DBusPreallocatedSend *preallocated,
01960                                                        DBusMessage          *message,
01961                                                        dbus_uint32_t        *client_serial)
01962 {
01963   dbus_uint32_t serial;
01964 
01965   preallocated->queue_link->data = message;
01966   _dbus_list_prepend_link (&connection->outgoing_messages,
01967                            preallocated->queue_link);
01968 
01969   _dbus_message_add_counter_link (message,
01970                                   preallocated->counter_link);
01971 
01972   dbus_free (preallocated);
01973   preallocated = NULL;
01974   
01975   dbus_message_ref (message);
01976   
01977   connection->n_outgoing += 1;
01978 
01979   _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01980                  message,
01981                  dbus_message_type_to_string (dbus_message_get_type (message)),
01982                  dbus_message_get_path (message) ?
01983                  dbus_message_get_path (message) :
01984                  "no path",
01985                  dbus_message_get_interface (message) ?
01986                  dbus_message_get_interface (message) :
01987                  "no interface",
01988                  dbus_message_get_member (message) ?
01989                  dbus_message_get_member (message) :
01990                  "no member",
01991                  dbus_message_get_signature (message),
01992                  dbus_message_get_destination (message) ?
01993                  dbus_message_get_destination (message) :
01994                  "null",
01995                  connection,
01996                  connection->n_outgoing);
01997 
01998   if (dbus_message_get_serial (message) == 0)
01999     {
02000       serial = _dbus_connection_get_next_client_serial (connection);
02001       dbus_message_set_serial (message, serial);
02002       if (client_serial)
02003         *client_serial = serial;
02004     }
02005   else
02006     {
02007       if (client_serial)
02008         *client_serial = dbus_message_get_serial (message);
02009     }
02010 
02011   _dbus_verbose ("Message %p serial is %u\n",
02012                  message, dbus_message_get_serial (message));
02013   
02014   dbus_message_lock (message);
02015 
02016   /* Now we need to run an iteration to hopefully just write the messages
02017    * out immediately, and otherwise get them queued up
02018    */
02019   _dbus_connection_do_iteration_unlocked (connection,
02020                                           NULL,
02021                                           DBUS_ITERATION_DO_WRITING,
02022                                           -1);
02023 
02024   /* If stuff is still queued up, be sure we wake up the main loop */
02025   if (connection->n_outgoing > 0)
02026     _dbus_connection_wakeup_mainloop (connection);
02027 }
02028 
02029 static void
02030 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02031                                                DBusPreallocatedSend *preallocated,
02032                                                DBusMessage          *message,
02033                                                dbus_uint32_t        *client_serial)
02034 {
02035   DBusDispatchStatus status;
02036 
02037   HAVE_LOCK_CHECK (connection);
02038   
02039   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02040                                                          preallocated,
02041                                                          message, client_serial);
02042 
02043   _dbus_verbose ("middle\n");
02044   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02045 
02046   /* this calls out to user code */
02047   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02048 }
02049 
02059 dbus_bool_t
02060 _dbus_connection_send_and_unlock (DBusConnection *connection,
02061                                   DBusMessage    *message,
02062                                   dbus_uint32_t  *client_serial)
02063 {
02064   DBusPreallocatedSend *preallocated;
02065 
02066   _dbus_assert (connection != NULL);
02067   _dbus_assert (message != NULL);
02068   
02069   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02070   if (preallocated == NULL)
02071     {
02072       CONNECTION_UNLOCK (connection);
02073       return FALSE;
02074     }
02075 
02076   _dbus_connection_send_preallocated_and_unlock (connection,
02077                                                  preallocated,
02078                                                  message,
02079                                                  client_serial);
02080   return TRUE;
02081 }
02082 
02107 void
02108 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02109 {
02110   dbus_int32_t tmp_refcount;
02111 
02112   CONNECTION_LOCK (connection);
02113 
02114   /* We increment and then decrement the refcount, because there is no
02115    * _dbus_atomic_get (mirroring the fact that there's no InterlockedGet
02116    * on Windows). */
02117   _dbus_atomic_inc (&connection->refcount);
02118   tmp_refcount = _dbus_atomic_dec (&connection->refcount);
02119 
02120   /* The caller should have one ref, and this function temporarily took
02121    * one more, which is reflected in this count even though we already
02122    * released it (relying on the caller's ref) due to _dbus_atomic_dec
02123    * semantics */
02124   _dbus_assert (tmp_refcount >= 2);
02125 
02126   if (tmp_refcount == 2)
02127     _dbus_connection_close_possibly_shared_and_unlock (connection);
02128   else
02129     CONNECTION_UNLOCK (connection);
02130 }
02131 
02132 
02142 static void
02143 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02144 {
02145   if (timeout_milliseconds == -1)
02146     _dbus_sleep_milliseconds (1000);
02147   else if (timeout_milliseconds < 100)
02148     ; /* just busy loop */
02149   else if (timeout_milliseconds <= 1000)
02150     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02151   else
02152     _dbus_sleep_milliseconds (1000);
02153 }
02154 
02155 static DBusMessage *
02156 generate_local_error_message (dbus_uint32_t serial, 
02157                               char *error_name, 
02158                               char *error_msg)
02159 {
02160   DBusMessage *message;
02161   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02162   if (!message)
02163     goto out;
02164 
02165   if (!dbus_message_set_error_name (message, error_name))
02166     {
02167       dbus_message_unref (message);
02168       message = NULL;
02169       goto out; 
02170     }
02171 
02172   dbus_message_set_no_reply (message, TRUE); 
02173 
02174   if (!dbus_message_set_reply_serial (message,
02175                                       serial))
02176     {
02177       dbus_message_unref (message);
02178       message = NULL;
02179       goto out;
02180     }
02181 
02182   if (error_msg != NULL)
02183     {
02184       DBusMessageIter iter;
02185 
02186       dbus_message_iter_init_append (message, &iter);
02187       if (!dbus_message_iter_append_basic (&iter,
02188                                            DBUS_TYPE_STRING,
02189                                            &error_msg))
02190         {
02191           dbus_message_unref (message);
02192           message = NULL;
02193           goto out;
02194         }
02195     }
02196 
02197  out:
02198   return message;
02199 }
02200 
02201 /*
02202  * Peek the incoming queue to see if we got reply for a specific serial
02203  */
02204 static dbus_bool_t
02205 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02206                                           dbus_uint32_t   client_serial)
02207 {
02208   DBusList *link;
02209   HAVE_LOCK_CHECK (connection);
02210 
02211   link = _dbus_list_get_first_link (&connection->incoming_messages);
02212 
02213   while (link != NULL)
02214     {
02215       DBusMessage *reply = link->data;
02216 
02217       if (dbus_message_get_reply_serial (reply) == client_serial)
02218         {
02219           _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02220           return TRUE;
02221         }
02222       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02223     }
02224 
02225   return FALSE;
02226 }
02227 
02228 /* This is slightly strange since we can pop a message here without
02229  * the dispatch lock.
02230  */
02231 static DBusMessage*
02232 check_for_reply_unlocked (DBusConnection *connection,
02233                           dbus_uint32_t   client_serial)
02234 {
02235   DBusList *link;
02236 
02237   HAVE_LOCK_CHECK (connection);
02238   
02239   link = _dbus_list_get_first_link (&connection->incoming_messages);
02240 
02241   while (link != NULL)
02242     {
02243       DBusMessage *reply = link->data;
02244 
02245       if (dbus_message_get_reply_serial (reply) == client_serial)
02246         {
02247           _dbus_list_remove_link (&connection->incoming_messages, link);
02248           connection->n_incoming  -= 1;
02249           return reply;
02250         }
02251       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02252     }
02253 
02254   return NULL;
02255 }
02256 
02257 static void
02258 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02259 {
02260    /* We can't iterate over the hash in the normal way since we'll be
02261     * dropping the lock for each item. So we restart the
02262     * iter each time as we drain the hash table.
02263     */
02264    
02265    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02266     {
02267       DBusPendingCall *pending;
02268       DBusHashIter iter;
02269       
02270       _dbus_hash_iter_init (connection->pending_replies, &iter);
02271       _dbus_hash_iter_next (&iter);
02272        
02273       pending = _dbus_hash_iter_get_value (&iter);
02274       _dbus_pending_call_ref_unlocked (pending);
02275        
02276       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02277                                                        connection);
02278 
02279       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02280           _dbus_connection_remove_timeout_unlocked (connection,
02281                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02282       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02283       _dbus_hash_iter_remove_entry (&iter);
02284 
02285       _dbus_pending_call_unref_and_unlock (pending);
02286       CONNECTION_LOCK (connection);
02287     }
02288   HAVE_LOCK_CHECK (connection);
02289 }
02290 
02291 static void
02292 complete_pending_call_and_unlock (DBusConnection  *connection,
02293                                   DBusPendingCall *pending,
02294                                   DBusMessage     *message)
02295 {
02296   _dbus_pending_call_set_reply_unlocked (pending, message);
02297   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02298   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02299  
02300   /* Must be called unlocked since it invokes app callback */
02301   _dbus_pending_call_complete (pending);
02302   dbus_pending_call_unref (pending);
02303 }
02304 
02305 static dbus_bool_t
02306 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02307                                               DBusPendingCall *pending)
02308 {
02309   DBusMessage *reply;
02310   DBusDispatchStatus status;
02311 
02312   reply = check_for_reply_unlocked (connection, 
02313                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02314   if (reply != NULL)
02315     {
02316       _dbus_verbose ("checked for reply\n");
02317 
02318       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02319 
02320       complete_pending_call_and_unlock (connection, pending, reply);
02321       dbus_message_unref (reply);
02322 
02323       CONNECTION_LOCK (connection);
02324       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02325       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02326       dbus_pending_call_unref (pending);
02327 
02328       return TRUE;
02329     }
02330 
02331   return FALSE;
02332 }
02333 
02348 void
02349 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02350 {
02351   long start_tv_sec, start_tv_usec;
02352   long tv_sec, tv_usec;
02353   DBusDispatchStatus status;
02354   DBusConnection *connection;
02355   dbus_uint32_t client_serial;
02356   DBusTimeout *timeout;
02357   int timeout_milliseconds, elapsed_milliseconds;
02358 
02359   _dbus_assert (pending != NULL);
02360 
02361   if (dbus_pending_call_get_completed (pending))
02362     return;
02363 
02364   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02365 
02366   connection = _dbus_pending_call_get_connection_and_lock (pending);
02367   
02368   /* Flush message queue - note, can affect dispatch status */
02369   _dbus_connection_flush_unlocked (connection);
02370 
02371   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02372 
02373   /* note that timeout_milliseconds is limited to a smallish value
02374    * in _dbus_pending_call_new() so overflows aren't possible
02375    * below
02376    */
02377   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02378   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02379   if (timeout)
02380     {
02381       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02382 
02383       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02384                      timeout_milliseconds,
02385                      client_serial,
02386                      start_tv_sec, start_tv_usec);
02387     }
02388   else
02389     {
02390       timeout_milliseconds = -1;
02391 
02392       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02393     }
02394 
02395   /* check to see if we already got the data off the socket */
02396   /* from another blocked pending call */
02397   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02398     return;
02399 
02400   /* Now we wait... */
02401   /* always block at least once as we know we don't have the reply yet */
02402   _dbus_connection_do_iteration_unlocked (connection,
02403                                           pending,
02404                                           DBUS_ITERATION_DO_READING |
02405                                           DBUS_ITERATION_BLOCK,
02406                                           timeout_milliseconds);
02407 
02408  recheck_status:
02409 
02410   _dbus_verbose ("top of recheck\n");
02411   
02412   HAVE_LOCK_CHECK (connection);
02413   
02414   /* queue messages and get status */
02415 
02416   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02417 
02418   /* the get_completed() is in case a dispatch() while we were blocking
02419    * got the reply instead of us.
02420    */
02421   if (_dbus_pending_call_get_completed_unlocked (pending))
02422     {
02423       _dbus_verbose ("Pending call completed by dispatch\n");
02424       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02425       dbus_pending_call_unref (pending);
02426       return;
02427     }
02428   
02429   if (status == DBUS_DISPATCH_DATA_REMAINS)
02430     {
02431       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02432         return;
02433     }
02434   
02435   _dbus_get_current_time (&tv_sec, &tv_usec);
02436   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02437           (tv_usec - start_tv_usec) / 1000;
02438   
02439   if (!_dbus_connection_get_is_connected_unlocked (connection))
02440     {
02441       DBusMessage *error_msg;
02442 
02443       error_msg = generate_local_error_message (client_serial,
02444                                                 DBUS_ERROR_DISCONNECTED, 
02445                                                 "Connection was disconnected before a reply was received"); 
02446 
02447       /* on OOM error_msg is set to NULL */
02448       complete_pending_call_and_unlock (connection, pending, error_msg);
02449       dbus_pending_call_unref (pending);
02450       return;
02451     }
02452   else if (connection->disconnect_message_link == NULL)
02453     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02454   else if (timeout == NULL)
02455     {
02456        if (status == DBUS_DISPATCH_NEED_MEMORY)
02457         {
02458           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02459            * we may already have a reply in the buffer and just can't process
02460            * it.
02461            */
02462           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02463 
02464           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02465         }
02466       else
02467         {          
02468           /* block again, we don't have the reply buffered yet. */
02469           _dbus_connection_do_iteration_unlocked (connection,
02470                                                   pending,
02471                                                   DBUS_ITERATION_DO_READING |
02472                                                   DBUS_ITERATION_BLOCK,
02473                                                   timeout_milliseconds - elapsed_milliseconds);
02474         }
02475 
02476       goto recheck_status;
02477     }
02478   else if (tv_sec < start_tv_sec)
02479     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02480   else if (elapsed_milliseconds < timeout_milliseconds)
02481     {
02482       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02483       
02484       if (status == DBUS_DISPATCH_NEED_MEMORY)
02485         {
02486           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02487            * we may already have a reply in the buffer and just can't process
02488            * it.
02489            */
02490           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02491 
02492           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02493         }
02494       else
02495         {          
02496           /* block again, we don't have the reply buffered yet. */
02497           _dbus_connection_do_iteration_unlocked (connection,
02498                                                   NULL,
02499                                                   DBUS_ITERATION_DO_READING |
02500                                                   DBUS_ITERATION_BLOCK,
02501                                                   timeout_milliseconds - elapsed_milliseconds);
02502         }
02503 
02504       goto recheck_status;
02505     }
02506 
02507   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02508                  elapsed_milliseconds);
02509 
02510   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02511   
02512   /* unlock and call user code */
02513   complete_pending_call_and_unlock (connection, pending, NULL);
02514 
02515   /* update user code on dispatch status */
02516   CONNECTION_LOCK (connection);
02517   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02518   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02519   dbus_pending_call_unref (pending);
02520 }
02521 
02558 DBusConnection*
02559 dbus_connection_open (const char     *address,
02560                       DBusError      *error)
02561 {
02562   DBusConnection *connection;
02563 
02564   _dbus_return_val_if_fail (address != NULL, NULL);
02565   _dbus_return_val_if_error_is_set (error, NULL);
02566 
02567   connection = _dbus_connection_open_internal (address,
02568                                                TRUE,
02569                                                error);
02570 
02571   return connection;
02572 }
02573 
02601 DBusConnection*
02602 dbus_connection_open_private (const char     *address,
02603                               DBusError      *error)
02604 {
02605   DBusConnection *connection;
02606 
02607   _dbus_return_val_if_fail (address != NULL, NULL);
02608   _dbus_return_val_if_error_is_set (error, NULL);
02609 
02610   connection = _dbus_connection_open_internal (address,
02611                                                FALSE,
02612                                                error);
02613 
02614   return connection;
02615 }
02616 
02623 DBusConnection *
02624 dbus_connection_ref (DBusConnection *connection)
02625 {
02626   _dbus_return_val_if_fail (connection != NULL, NULL);
02627   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02628 
02629   _dbus_atomic_inc (&connection->refcount);
02630 
02631   return connection;
02632 }
02633 
02634 static void
02635 free_outgoing_message (void *element,
02636                        void *data)
02637 {
02638   DBusMessage *message = element;
02639   DBusConnection *connection = data;
02640 
02641   _dbus_message_remove_counter (message,
02642                                 connection->outgoing_counter,
02643                                 NULL);
02644   dbus_message_unref (message);
02645 }
02646 
02647 /* This is run without the mutex held, but after the last reference
02648  * to the connection has been dropped we should have no thread-related
02649  * problems
02650  */
02651 static void
02652 _dbus_connection_last_unref (DBusConnection *connection)
02653 {
02654   DBusList *link;
02655 
02656   _dbus_verbose ("Finalizing connection %p\n", connection);
02657   
02658   _dbus_assert (connection->refcount.value == 0);
02659   
02660   /* You have to disconnect the connection before unref:ing it. Otherwise
02661    * you won't get the disconnected message.
02662    */
02663   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02664   _dbus_assert (connection->server_guid == NULL);
02665   
02666   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02667   _dbus_object_tree_free_all_unlocked (connection->objects);
02668   
02669   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02670   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02671   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02672   
02673   _dbus_watch_list_free (connection->watches);
02674   connection->watches = NULL;
02675   
02676   _dbus_timeout_list_free (connection->timeouts);
02677   connection->timeouts = NULL;
02678 
02679   _dbus_data_slot_list_free (&connection->slot_list);
02680   
02681   link = _dbus_list_get_first_link (&connection->filter_list);
02682   while (link != NULL)
02683     {
02684       DBusMessageFilter *filter = link->data;
02685       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02686 
02687       filter->function = NULL;
02688       _dbus_message_filter_unref (filter); /* calls app callback */
02689       link->data = NULL;
02690       
02691       link = next;
02692     }
02693   _dbus_list_clear (&connection->filter_list);
02694   
02695   /* ---- Done with stuff that invokes application callbacks */
02696 
02697   _dbus_object_tree_unref (connection->objects);  
02698 
02699   _dbus_hash_table_unref (connection->pending_replies);
02700   connection->pending_replies = NULL;
02701   
02702   _dbus_list_clear (&connection->filter_list);
02703   
02704   _dbus_list_foreach (&connection->outgoing_messages,
02705                       free_outgoing_message,
02706                       connection);
02707   _dbus_list_clear (&connection->outgoing_messages);
02708   
02709   _dbus_list_foreach (&connection->incoming_messages,
02710                       (DBusForeachFunction) dbus_message_unref,
02711                       NULL);
02712   _dbus_list_clear (&connection->incoming_messages);
02713 
02714   _dbus_counter_unref (connection->outgoing_counter);
02715 
02716   _dbus_transport_unref (connection->transport);
02717 
02718   if (connection->disconnect_message_link)
02719     {
02720       DBusMessage *message = connection->disconnect_message_link->data;
02721       dbus_message_unref (message);
02722       _dbus_list_free_link (connection->disconnect_message_link);
02723     }
02724 
02725   _dbus_list_clear (&connection->link_cache);
02726   
02727   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02728   _dbus_condvar_free_at_location (&connection->io_path_cond);
02729 
02730   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02731   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02732 
02733   _dbus_mutex_free_at_location (&connection->slot_mutex);
02734 
02735   _dbus_mutex_free_at_location (&connection->mutex);
02736   
02737   dbus_free (connection);
02738 }
02739 
02759 void
02760 dbus_connection_unref (DBusConnection *connection)
02761 {
02762   dbus_bool_t last_unref;
02763 
02764   _dbus_return_if_fail (connection != NULL);
02765   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02766 
02767   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02768 
02769   if (last_unref)
02770     {
02771 #ifndef DBUS_DISABLE_CHECKS
02772       if (_dbus_transport_get_is_connected (connection->transport))
02773         {
02774           _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",
02775                                    connection->shareable ?
02776                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02777                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02778           return;
02779         }
02780 #endif
02781       _dbus_connection_last_unref (connection);
02782     }
02783 }
02784 
02785 /*
02786  * Note that the transport can disconnect itself (other end drops us)
02787  * and in that case this function never runs. So this function must
02788  * not do anything more than disconnect the transport and update the
02789  * dispatch status.
02790  * 
02791  * If the transport self-disconnects, then we assume someone will
02792  * dispatch the connection to cause the dispatch status update.
02793  */
02794 static void
02795 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02796 {
02797   DBusDispatchStatus status;
02798 
02799   HAVE_LOCK_CHECK (connection);
02800   
02801   _dbus_verbose ("Disconnecting %p\n", connection);
02802 
02803   /* We need to ref because update_dispatch_status_and_unlock will unref
02804    * the connection if it was shared and libdbus was the only remaining
02805    * refcount holder.
02806    */
02807   _dbus_connection_ref_unlocked (connection);
02808   
02809   _dbus_transport_disconnect (connection->transport);
02810 
02811   /* This has the side effect of queuing the disconnect message link
02812    * (unless we don't have enough memory, possibly, so don't assert it).
02813    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02814    * should never again return the newly-disconnected connection.
02815    *
02816    * However, we only unref the shared connection and exit_on_disconnect when
02817    * the disconnect message reaches the head of the message queue,
02818    * NOT when it's first queued.
02819    */
02820   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02821 
02822   /* This calls out to user code */
02823   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02824 
02825   /* Could also call out to user code */
02826   dbus_connection_unref (connection);
02827 }
02828 
02871 void
02872 dbus_connection_close (DBusConnection *connection)
02873 {
02874   _dbus_return_if_fail (connection != NULL);
02875   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02876 
02877   CONNECTION_LOCK (connection);
02878 
02879 #ifndef DBUS_DISABLE_CHECKS
02880   if (connection->shareable)
02881     {
02882       CONNECTION_UNLOCK (connection);
02883 
02884       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02885       return;
02886     }
02887 #endif
02888   
02889   _dbus_connection_close_possibly_shared_and_unlock (connection);
02890 }
02891 
02892 static dbus_bool_t
02893 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02894 {
02895   HAVE_LOCK_CHECK (connection);
02896   return _dbus_transport_get_is_connected (connection->transport);
02897 }
02898 
02912 dbus_bool_t
02913 dbus_connection_get_is_connected (DBusConnection *connection)
02914 {
02915   dbus_bool_t res;
02916 
02917   _dbus_return_val_if_fail (connection != NULL, FALSE);
02918   
02919   CONNECTION_LOCK (connection);
02920   res = _dbus_connection_get_is_connected_unlocked (connection);
02921   CONNECTION_UNLOCK (connection);
02922   
02923   return res;
02924 }
02925 
02934 dbus_bool_t
02935 dbus_connection_get_is_authenticated (DBusConnection *connection)
02936 {
02937   dbus_bool_t res;
02938 
02939   _dbus_return_val_if_fail (connection != NULL, FALSE);
02940   
02941   CONNECTION_LOCK (connection);
02942   res = _dbus_transport_get_is_authenticated (connection->transport);
02943   CONNECTION_UNLOCK (connection);
02944   
02945   return res;
02946 }
02947 
02968 dbus_bool_t
02969 dbus_connection_get_is_anonymous (DBusConnection *connection)
02970 {
02971   dbus_bool_t res;
02972 
02973   _dbus_return_val_if_fail (connection != NULL, FALSE);
02974   
02975   CONNECTION_LOCK (connection);
02976   res = _dbus_transport_get_is_anonymous (connection->transport);
02977   CONNECTION_UNLOCK (connection);
02978   
02979   return res;
02980 }
02981 
03013 char*
03014 dbus_connection_get_server_id (DBusConnection *connection)
03015 {
03016   char *id;
03017 
03018   _dbus_return_val_if_fail (connection != NULL, NULL);
03019 
03020   CONNECTION_LOCK (connection);
03021   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03022   CONNECTION_UNLOCK (connection);
03023 
03024   return id;
03025 }
03026 
03044 dbus_bool_t
03045 dbus_connection_can_send_type(DBusConnection *connection,
03046                                   int type)
03047 {
03048   _dbus_return_val_if_fail (connection != NULL, FALSE);
03049 
03050   if (!_dbus_type_is_valid(type))
03051     return FALSE;
03052 
03053   if (type != DBUS_TYPE_UNIX_FD)
03054     return TRUE;
03055 
03056 #ifdef HAVE_UNIX_FD_PASSING
03057   {
03058     dbus_bool_t b;
03059 
03060     CONNECTION_LOCK(connection);
03061     b = _dbus_transport_can_pass_unix_fd(connection->transport);
03062     CONNECTION_UNLOCK(connection);
03063 
03064     return b;
03065   }
03066 #endif
03067 
03068   return FALSE;
03069 }
03070 
03084 void
03085 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03086                                         dbus_bool_t     exit_on_disconnect)
03087 {
03088   _dbus_return_if_fail (connection != NULL);
03089 
03090   CONNECTION_LOCK (connection);
03091   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03092   CONNECTION_UNLOCK (connection);
03093 }
03094 
03104 DBusPreallocatedSend*
03105 dbus_connection_preallocate_send (DBusConnection *connection)
03106 {
03107   DBusPreallocatedSend *preallocated;
03108 
03109   _dbus_return_val_if_fail (connection != NULL, NULL);
03110 
03111   CONNECTION_LOCK (connection);
03112   
03113   preallocated =
03114     _dbus_connection_preallocate_send_unlocked (connection);
03115 
03116   CONNECTION_UNLOCK (connection);
03117 
03118   return preallocated;
03119 }
03120 
03130 void
03131 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03132                                         DBusPreallocatedSend *preallocated)
03133 {
03134   _dbus_return_if_fail (connection != NULL);
03135   _dbus_return_if_fail (preallocated != NULL);  
03136   _dbus_return_if_fail (connection == preallocated->connection);
03137 
03138   _dbus_list_free_link (preallocated->queue_link);
03139   _dbus_counter_unref (preallocated->counter_link->data);
03140   _dbus_list_free_link (preallocated->counter_link);
03141   dbus_free (preallocated);
03142 }
03143 
03156 void
03157 dbus_connection_send_preallocated (DBusConnection       *connection,
03158                                    DBusPreallocatedSend *preallocated,
03159                                    DBusMessage          *message,
03160                                    dbus_uint32_t        *client_serial)
03161 {
03162   _dbus_return_if_fail (connection != NULL);
03163   _dbus_return_if_fail (preallocated != NULL);
03164   _dbus_return_if_fail (message != NULL);
03165   _dbus_return_if_fail (preallocated->connection == connection);
03166   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03167                         dbus_message_get_member (message) != NULL);
03168   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03169                         (dbus_message_get_interface (message) != NULL &&
03170                          dbus_message_get_member (message) != NULL));
03171 
03172   CONNECTION_LOCK (connection);
03173 
03174 #ifdef HAVE_UNIX_FD_PASSING
03175 
03176   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03177       message->n_unix_fds > 0)
03178     {
03179       /* Refuse to send fds on a connection that cannot handle
03180          them. Unfortunately we cannot return a proper error here, so
03181          the best we can is just return. */
03182       CONNECTION_UNLOCK (connection);
03183       return;
03184     }
03185 
03186 #endif
03187 
03188   _dbus_connection_send_preallocated_and_unlock (connection,
03189                                                  preallocated,
03190                                                  message, client_serial);
03191 }
03192 
03193 static dbus_bool_t
03194 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03195                                           DBusMessage    *message,
03196                                           dbus_uint32_t  *client_serial)
03197 {
03198   DBusPreallocatedSend *preallocated;
03199 
03200   _dbus_assert (connection != NULL);
03201   _dbus_assert (message != NULL);
03202   
03203   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03204   if (preallocated == NULL)
03205     return FALSE;
03206 
03207   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03208                                                          preallocated,
03209                                                          message,
03210                                                          client_serial);
03211   return TRUE;
03212 }
03213 
03241 dbus_bool_t
03242 dbus_connection_send (DBusConnection *connection,
03243                       DBusMessage    *message,
03244                       dbus_uint32_t  *serial)
03245 {
03246   _dbus_return_val_if_fail (connection != NULL, FALSE);
03247   _dbus_return_val_if_fail (message != NULL, FALSE);
03248 
03249   CONNECTION_LOCK (connection);
03250 
03251 #ifdef HAVE_UNIX_FD_PASSING
03252 
03253   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03254       message->n_unix_fds > 0)
03255     {
03256       /* Refuse to send fds on a connection that cannot handle
03257          them. Unfortunately we cannot return a proper error here, so
03258          the best we can is just return. */
03259       CONNECTION_UNLOCK (connection);
03260       return FALSE;
03261     }
03262 
03263 #endif
03264 
03265   return _dbus_connection_send_and_unlock (connection,
03266                                            message,
03267                                            serial);
03268 }
03269 
03270 static dbus_bool_t
03271 reply_handler_timeout (void *data)
03272 {
03273   DBusConnection *connection;
03274   DBusDispatchStatus status;
03275   DBusPendingCall *pending = data;
03276 
03277   connection = _dbus_pending_call_get_connection_and_lock (pending);
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   
03291   return TRUE;
03292 }
03293 
03336 dbus_bool_t
03337 dbus_connection_send_with_reply (DBusConnection     *connection,
03338                                  DBusMessage        *message,
03339                                  DBusPendingCall   **pending_return,
03340                                  int                 timeout_milliseconds)
03341 {
03342   DBusPendingCall *pending;
03343   dbus_int32_t serial = -1;
03344   DBusDispatchStatus status;
03345 
03346   _dbus_return_val_if_fail (connection != NULL, FALSE);
03347   _dbus_return_val_if_fail (message != NULL, FALSE);
03348   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03349 
03350   if (pending_return)
03351     *pending_return = NULL;
03352 
03353   CONNECTION_LOCK (connection);
03354 
03355 #ifdef HAVE_UNIX_FD_PASSING
03356 
03357   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03358       message->n_unix_fds > 0)
03359     {
03360       /* Refuse to send fds on a connection that cannot handle
03361          them. Unfortunately we cannot return a proper error here, so
03362          the best we can do is return TRUE but leave *pending_return
03363          as NULL. */
03364       CONNECTION_UNLOCK (connection);
03365       return TRUE;
03366     }
03367 
03368 #endif
03369 
03370    if (!_dbus_connection_get_is_connected_unlocked (connection))
03371     {
03372       CONNECTION_UNLOCK (connection);
03373 
03374       return TRUE;
03375     }
03376 
03377   pending = _dbus_pending_call_new_unlocked (connection,
03378                                              timeout_milliseconds,
03379                                              reply_handler_timeout);
03380 
03381   if (pending == NULL)
03382     {
03383       CONNECTION_UNLOCK (connection);
03384       return FALSE;
03385     }
03386 
03387   /* Assign a serial to the message */
03388   serial = dbus_message_get_serial (message);
03389   if (serial == 0)
03390     {
03391       serial = _dbus_connection_get_next_client_serial (connection);
03392       dbus_message_set_serial (message, serial);
03393     }
03394 
03395   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03396     goto error;
03397     
03398   /* Insert the serial in the pending replies hash;
03399    * hash takes a refcount on DBusPendingCall.
03400    * Also, add the timeout.
03401    */
03402   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03403                                                       pending))
03404     goto error;
03405  
03406   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03407     {
03408       _dbus_connection_detach_pending_call_and_unlock (connection,
03409                                                        pending);
03410       goto error_unlocked;
03411     }
03412 
03413   if (pending_return)
03414     *pending_return = pending; /* hand off refcount */
03415   else
03416     {
03417       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03418       /* we still have a ref to the pending call in this case, we unref
03419        * after unlocking, below
03420        */
03421     }
03422 
03423   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03424 
03425   /* this calls out to user code */
03426   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03427 
03428   if (pending_return == NULL)
03429     dbus_pending_call_unref (pending);
03430   
03431   return TRUE;
03432 
03433  error:
03434   CONNECTION_UNLOCK (connection);
03435  error_unlocked:
03436   dbus_pending_call_unref (pending);
03437   return FALSE;
03438 }
03439 
03472 DBusMessage*
03473 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03474                                            DBusMessage        *message,
03475                                            int                 timeout_milliseconds,
03476                                            DBusError          *error)
03477 {
03478   DBusMessage *reply;
03479   DBusPendingCall *pending;
03480 
03481   _dbus_return_val_if_fail (connection != NULL, NULL);
03482   _dbus_return_val_if_fail (message != NULL, NULL);
03483   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03484   _dbus_return_val_if_error_is_set (error, NULL);
03485 
03486 #ifdef HAVE_UNIX_FD_PASSING
03487 
03488   CONNECTION_LOCK (connection);
03489   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03490       message->n_unix_fds > 0)
03491     {
03492       CONNECTION_UNLOCK (connection);
03493       dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03494       return NULL;
03495     }
03496   CONNECTION_UNLOCK (connection);
03497 
03498 #endif
03499 
03500   if (!dbus_connection_send_with_reply (connection, message,
03501                                         &pending, timeout_milliseconds))
03502     {
03503       _DBUS_SET_OOM (error);
03504       return NULL;
03505     }
03506 
03507   if (pending == NULL)
03508     {
03509       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03510       return NULL;
03511     }
03512   
03513   dbus_pending_call_block (pending);
03514 
03515   reply = dbus_pending_call_steal_reply (pending);
03516   dbus_pending_call_unref (pending);
03517 
03518   /* call_complete_and_unlock() called from pending_call_block() should
03519    * always fill this in.
03520    */
03521   _dbus_assert (reply != NULL);
03522   
03523    if (dbus_set_error_from_message (error, reply))
03524     {
03525       dbus_message_unref (reply);
03526       return NULL;
03527     }
03528   else
03529     return reply;
03530 }
03531 
03540 static DBusDispatchStatus
03541 _dbus_connection_flush_unlocked (DBusConnection *connection)
03542 {
03543   /* We have to specify DBUS_ITERATION_DO_READING here because
03544    * otherwise we could have two apps deadlock if they are both doing
03545    * a flush(), and the kernel buffers fill up. This could change the
03546    * dispatch status.
03547    */
03548   DBusDispatchStatus status;
03549 
03550   HAVE_LOCK_CHECK (connection);
03551   
03552   while (connection->n_outgoing > 0 &&
03553          _dbus_connection_get_is_connected_unlocked (connection))
03554     {
03555       _dbus_verbose ("doing iteration in\n");
03556       HAVE_LOCK_CHECK (connection);
03557       _dbus_connection_do_iteration_unlocked (connection,
03558                                               NULL,
03559                                               DBUS_ITERATION_DO_READING |
03560                                               DBUS_ITERATION_DO_WRITING |
03561                                               DBUS_ITERATION_BLOCK,
03562                                               -1);
03563     }
03564 
03565   HAVE_LOCK_CHECK (connection);
03566   _dbus_verbose ("middle\n");
03567   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03568 
03569   HAVE_LOCK_CHECK (connection);
03570   return status;
03571 }
03572 
03578 void
03579 dbus_connection_flush (DBusConnection *connection)
03580 {
03581   /* We have to specify DBUS_ITERATION_DO_READING here because
03582    * otherwise we could have two apps deadlock if they are both doing
03583    * a flush(), and the kernel buffers fill up. This could change the
03584    * dispatch status.
03585    */
03586   DBusDispatchStatus status;
03587 
03588   _dbus_return_if_fail (connection != NULL);
03589   
03590   CONNECTION_LOCK (connection);
03591 
03592   status = _dbus_connection_flush_unlocked (connection);
03593   
03594   HAVE_LOCK_CHECK (connection);
03595   /* Unlocks and calls out to user code */
03596   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03597 
03598   _dbus_verbose ("end\n");
03599 }
03600 
03611 static dbus_bool_t
03612 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03613                                      int             timeout_milliseconds, 
03614                                      dbus_bool_t     dispatch)
03615 {
03616   DBusDispatchStatus dstatus;
03617   dbus_bool_t progress_possible;
03618 
03619   /* Need to grab a ref here in case we're a private connection and
03620    * the user drops the last ref in a handler we call; see bug 
03621    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03622    */
03623   dbus_connection_ref (connection);
03624   dstatus = dbus_connection_get_dispatch_status (connection);
03625 
03626   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03627     {
03628       _dbus_verbose ("doing dispatch\n");
03629       dbus_connection_dispatch (connection);
03630       CONNECTION_LOCK (connection);
03631     }
03632   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03633     {
03634       _dbus_verbose ("pausing for memory\n");
03635       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03636       CONNECTION_LOCK (connection);
03637     }
03638   else
03639     {
03640       CONNECTION_LOCK (connection);
03641       if (_dbus_connection_get_is_connected_unlocked (connection))
03642         {
03643           _dbus_verbose ("doing iteration\n");
03644           _dbus_connection_do_iteration_unlocked (connection,
03645                                                   NULL,
03646                                                   DBUS_ITERATION_DO_READING |
03647                                                   DBUS_ITERATION_DO_WRITING |
03648                                                   DBUS_ITERATION_BLOCK,
03649                                                   timeout_milliseconds);
03650         }
03651     }
03652   
03653   HAVE_LOCK_CHECK (connection);
03654   /* If we can dispatch, we can make progress until the Disconnected message
03655    * has been processed; if we can only read/write, we can make progress
03656    * as long as the transport is open.
03657    */
03658   if (dispatch)
03659     progress_possible = connection->n_incoming != 0 ||
03660       connection->disconnect_message_link != NULL;
03661   else
03662     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03663 
03664   CONNECTION_UNLOCK (connection);
03665 
03666   dbus_connection_unref (connection);
03667 
03668   return progress_possible; /* TRUE if we can make more progress */
03669 }
03670 
03671 
03706 dbus_bool_t
03707 dbus_connection_read_write_dispatch (DBusConnection *connection,
03708                                      int             timeout_milliseconds)
03709 {
03710   _dbus_return_val_if_fail (connection != NULL, FALSE);
03711   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03712    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03713 }
03714 
03738 dbus_bool_t 
03739 dbus_connection_read_write (DBusConnection *connection, 
03740                             int             timeout_milliseconds) 
03741 { 
03742   _dbus_return_val_if_fail (connection != NULL, FALSE);
03743   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03744    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03745 }
03746 
03747 /* We need to call this anytime we pop the head of the queue, and then
03748  * update_dispatch_status_and_unlock needs to be called afterward
03749  * which will "process" the disconnected message and set
03750  * disconnected_message_processed.
03751  */
03752 static void
03753 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03754                                              DBusMessage    *head_of_queue)
03755 {
03756   HAVE_LOCK_CHECK (connection);
03757 
03758   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03759   if (connection->disconnect_message_link == NULL &&
03760       dbus_message_is_signal (head_of_queue,
03761                               DBUS_INTERFACE_LOCAL,
03762                               "Disconnected"))
03763     {
03764       connection->disconnected_message_arrived = TRUE;
03765     }
03766 }
03767 
03787 DBusMessage*
03788 dbus_connection_borrow_message (DBusConnection *connection)
03789 {
03790   DBusDispatchStatus status;
03791   DBusMessage *message;
03792 
03793   _dbus_return_val_if_fail (connection != NULL, NULL);
03794 
03795   _dbus_verbose ("start\n");
03796   
03797   /* this is called for the side effect that it queues
03798    * up any messages from the transport
03799    */
03800   status = dbus_connection_get_dispatch_status (connection);
03801   if (status != DBUS_DISPATCH_DATA_REMAINS)
03802     return NULL;
03803   
03804   CONNECTION_LOCK (connection);
03805 
03806   _dbus_connection_acquire_dispatch (connection);
03807 
03808   /* While a message is outstanding, the dispatch lock is held */
03809   _dbus_assert (connection->message_borrowed == NULL);
03810 
03811   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03812   
03813   message = connection->message_borrowed;
03814 
03815   check_disconnected_message_arrived_unlocked (connection, message);
03816   
03817   /* Note that we KEEP the dispatch lock until the message is returned */
03818   if (message == NULL)
03819     _dbus_connection_release_dispatch (connection);
03820 
03821   CONNECTION_UNLOCK (connection);
03822 
03823   /* We don't update dispatch status until it's returned or stolen */
03824   
03825   return message;
03826 }
03827 
03836 void
03837 dbus_connection_return_message (DBusConnection *connection,
03838                                 DBusMessage    *message)
03839 {
03840   DBusDispatchStatus status;
03841   
03842   _dbus_return_if_fail (connection != NULL);
03843   _dbus_return_if_fail (message != NULL);
03844   _dbus_return_if_fail (message == connection->message_borrowed);
03845   _dbus_return_if_fail (connection->dispatch_acquired);
03846   
03847   CONNECTION_LOCK (connection);
03848   
03849   _dbus_assert (message == connection->message_borrowed);
03850   
03851   connection->message_borrowed = NULL;
03852 
03853   _dbus_connection_release_dispatch (connection); 
03854 
03855   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03856   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03857 }
03858 
03868 void
03869 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03870                                         DBusMessage    *message)
03871 {
03872   DBusMessage *pop_message;
03873   DBusDispatchStatus status;
03874 
03875   _dbus_return_if_fail (connection != NULL);
03876   _dbus_return_if_fail (message != NULL);
03877   _dbus_return_if_fail (message == connection->message_borrowed);
03878   _dbus_return_if_fail (connection->dispatch_acquired);
03879   
03880   CONNECTION_LOCK (connection);
03881  
03882   _dbus_assert (message == connection->message_borrowed);
03883 
03884   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03885   _dbus_assert (message == pop_message);
03886   
03887   connection->n_incoming -= 1;
03888  
03889   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03890                  message, connection->n_incoming);
03891  
03892   connection->message_borrowed = NULL;
03893 
03894   _dbus_connection_release_dispatch (connection);
03895 
03896   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03897   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03898 }
03899 
03900 /* See dbus_connection_pop_message, but requires the caller to own
03901  * the lock before calling. May drop the lock while running.
03902  */
03903 static DBusList*
03904 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03905 {
03906   HAVE_LOCK_CHECK (connection);
03907   
03908   _dbus_assert (connection->message_borrowed == NULL);
03909   
03910   if (connection->n_incoming > 0)
03911     {
03912       DBusList *link;
03913 
03914       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03915       connection->n_incoming -= 1;
03916 
03917       _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03918                      link->data,
03919                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
03920                      dbus_message_get_path (link->data) ?
03921                      dbus_message_get_path (link->data) :
03922                      "no path",
03923                      dbus_message_get_interface (link->data) ?
03924                      dbus_message_get_interface (link->data) :
03925                      "no interface",
03926                      dbus_message_get_member (link->data) ?
03927                      dbus_message_get_member (link->data) :
03928                      "no member",
03929                      dbus_message_get_signature (link->data),
03930                      connection, connection->n_incoming);
03931 
03932       check_disconnected_message_arrived_unlocked (connection, link->data);
03933       
03934       return link;
03935     }
03936   else
03937     return NULL;
03938 }
03939 
03940 /* See dbus_connection_pop_message, but requires the caller to own
03941  * the lock before calling. May drop the lock while running.
03942  */
03943 static DBusMessage*
03944 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03945 {
03946   DBusList *link;
03947 
03948   HAVE_LOCK_CHECK (connection);
03949   
03950   link = _dbus_connection_pop_message_link_unlocked (connection);
03951 
03952   if (link != NULL)
03953     {
03954       DBusMessage *message;
03955       
03956       message = link->data;
03957       
03958       _dbus_list_free_link (link);
03959       
03960       return message;
03961     }
03962   else
03963     return NULL;
03964 }
03965 
03966 static void
03967 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03968                                                 DBusList       *message_link)
03969 {
03970   HAVE_LOCK_CHECK (connection);
03971   
03972   _dbus_assert (message_link != NULL);
03973   /* You can't borrow a message while a link is outstanding */
03974   _dbus_assert (connection->message_borrowed == NULL);
03975   /* We had to have the dispatch lock across the pop/putback */
03976   _dbus_assert (connection->dispatch_acquired);
03977 
03978   _dbus_list_prepend_link (&connection->incoming_messages,
03979                            message_link);
03980   connection->n_incoming += 1;
03981 
03982   _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
03983                  message_link->data,
03984                  dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
03985                  dbus_message_get_interface (message_link->data) ?
03986                  dbus_message_get_interface (message_link->data) :
03987                  "no interface",
03988                  dbus_message_get_member (message_link->data) ?
03989                  dbus_message_get_member (message_link->data) :
03990                  "no member",
03991                  dbus_message_get_signature (message_link->data),
03992                  connection, connection->n_incoming);
03993 }
03994 
04014 DBusMessage*
04015 dbus_connection_pop_message (DBusConnection *connection)
04016 {
04017   DBusMessage *message;
04018   DBusDispatchStatus status;
04019 
04020   _dbus_verbose ("start\n");
04021   
04022   /* this is called for the side effect that it queues
04023    * up any messages from the transport
04024    */
04025   status = dbus_connection_get_dispatch_status (connection);
04026   if (status != DBUS_DISPATCH_DATA_REMAINS)
04027     return NULL;
04028   
04029   CONNECTION_LOCK (connection);
04030   _dbus_connection_acquire_dispatch (connection);
04031   HAVE_LOCK_CHECK (connection);
04032   
04033   message = _dbus_connection_pop_message_unlocked (connection);
04034 
04035   _dbus_verbose ("Returning popped message %p\n", message);    
04036 
04037   _dbus_connection_release_dispatch (connection);
04038 
04039   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04040   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04041   
04042   return message;
04043 }
04044 
04052 static void
04053 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04054 {
04055   HAVE_LOCK_CHECK (connection);
04056 
04057   _dbus_connection_ref_unlocked (connection);
04058   CONNECTION_UNLOCK (connection);
04059   
04060   _dbus_verbose ("locking dispatch_mutex\n");
04061   _dbus_mutex_lock (connection->dispatch_mutex);
04062 
04063   while (connection->dispatch_acquired)
04064     {
04065       _dbus_verbose ("waiting for dispatch to be acquirable\n");
04066       _dbus_condvar_wait (connection->dispatch_cond, 
04067                           connection->dispatch_mutex);
04068     }
04069   
04070   _dbus_assert (!connection->dispatch_acquired);
04071 
04072   connection->dispatch_acquired = TRUE;
04073 
04074   _dbus_verbose ("unlocking dispatch_mutex\n");
04075   _dbus_mutex_unlock (connection->dispatch_mutex);
04076   
04077   CONNECTION_LOCK (connection);
04078   _dbus_connection_unref_unlocked (connection);
04079 }
04080 
04088 static void
04089 _dbus_connection_release_dispatch (DBusConnection *connection)
04090 {
04091   HAVE_LOCK_CHECK (connection);
04092   
04093   _dbus_verbose ("locking dispatch_mutex\n");
04094   _dbus_mutex_lock (connection->dispatch_mutex);
04095   
04096   _dbus_assert (connection->dispatch_acquired);
04097 
04098   connection->dispatch_acquired = FALSE;
04099   _dbus_condvar_wake_one (connection->dispatch_cond);
04100 
04101   _dbus_verbose ("unlocking dispatch_mutex\n");
04102   _dbus_mutex_unlock (connection->dispatch_mutex);
04103 }
04104 
04105 static void
04106 _dbus_connection_failed_pop (DBusConnection *connection,
04107                              DBusList       *message_link)
04108 {
04109   _dbus_list_prepend_link (&connection->incoming_messages,
04110                            message_link);
04111   connection->n_incoming += 1;
04112 }
04113 
04114 /* Note this may be called multiple times since we don't track whether we already did it */
04115 static void
04116 notify_disconnected_unlocked (DBusConnection *connection)
04117 {
04118   HAVE_LOCK_CHECK (connection);
04119 
04120   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04121    * connection from dbus_bus_get(). We make the same guarantee for
04122    * dbus_connection_open() but in a different way since we don't want to
04123    * unref right here; we instead check for connectedness before returning
04124    * the connection from the hash.
04125    */
04126   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04127 
04128   /* Dump the outgoing queue, we aren't going to be able to
04129    * send it now, and we'd like accessors like
04130    * dbus_connection_get_outgoing_size() to be accurate.
04131    */
04132   if (connection->n_outgoing > 0)
04133     {
04134       DBusList *link;
04135       
04136       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04137                      connection->n_outgoing);
04138       
04139       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04140         {
04141           _dbus_connection_message_sent (connection, link->data);
04142         }
04143     } 
04144 }
04145 
04146 /* Note this may be called multiple times since we don't track whether we already did it */
04147 static DBusDispatchStatus
04148 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04149 {
04150   HAVE_LOCK_CHECK (connection);
04151   
04152   if (connection->disconnect_message_link != NULL)
04153     {
04154       _dbus_verbose ("Sending disconnect message\n");
04155       
04156       /* If we have pending calls, queue their timeouts - we want the Disconnected
04157        * to be the last message, after these timeouts.
04158        */
04159       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04160       
04161       /* We haven't sent the disconnect message already,
04162        * and all real messages have been queued up.
04163        */
04164       _dbus_connection_queue_synthesized_message_link (connection,
04165                                                        connection->disconnect_message_link);
04166       connection->disconnect_message_link = NULL;
04167 
04168       return DBUS_DISPATCH_DATA_REMAINS;
04169     }
04170 
04171   return DBUS_DISPATCH_COMPLETE;
04172 }
04173 
04174 static DBusDispatchStatus
04175 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04176 {
04177   HAVE_LOCK_CHECK (connection);
04178   
04179   if (connection->n_incoming > 0)
04180     return DBUS_DISPATCH_DATA_REMAINS;
04181   else if (!_dbus_transport_queue_messages (connection->transport))
04182     return DBUS_DISPATCH_NEED_MEMORY;
04183   else
04184     {
04185       DBusDispatchStatus status;
04186       dbus_bool_t is_connected;
04187       
04188       status = _dbus_transport_get_dispatch_status (connection->transport);
04189       is_connected = _dbus_transport_get_is_connected (connection->transport);
04190 
04191       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04192                      DISPATCH_STATUS_NAME (status), is_connected);
04193       
04194       if (!is_connected)
04195         {
04196           /* It's possible this would be better done by having an explicit
04197            * notification from _dbus_transport_disconnect() that would
04198            * synchronously do this, instead of waiting for the next dispatch
04199            * status check. However, probably not good to change until it causes
04200            * a problem.
04201            */
04202           notify_disconnected_unlocked (connection);
04203 
04204           /* I'm not sure this is needed; the idea is that we want to
04205            * queue the Disconnected only after we've read all the
04206            * messages, but if we're disconnected maybe we are guaranteed
04207            * to have read them all ?
04208            */
04209           if (status == DBUS_DISPATCH_COMPLETE)
04210             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04211         }
04212       
04213       if (status != DBUS_DISPATCH_COMPLETE)
04214         return status;
04215       else if (connection->n_incoming > 0)
04216         return DBUS_DISPATCH_DATA_REMAINS;
04217       else
04218         return DBUS_DISPATCH_COMPLETE;
04219     }
04220 }
04221 
04222 static void
04223 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04224                                                     DBusDispatchStatus new_status)
04225 {
04226   dbus_bool_t changed;
04227   DBusDispatchStatusFunction function;
04228   void *data;
04229 
04230   HAVE_LOCK_CHECK (connection);
04231 
04232   _dbus_connection_ref_unlocked (connection);
04233 
04234   changed = new_status != connection->last_dispatch_status;
04235 
04236   connection->last_dispatch_status = new_status;
04237 
04238   function = connection->dispatch_status_function;
04239   data = connection->dispatch_status_data;
04240 
04241   if (connection->disconnected_message_arrived &&
04242       !connection->disconnected_message_processed)
04243     {
04244       connection->disconnected_message_processed = TRUE;
04245       
04246       /* this does an unref, but we have a ref
04247        * so we should not run the finalizer here
04248        * inside the lock.
04249        */
04250       connection_forget_shared_unlocked (connection);
04251 
04252       if (connection->exit_on_disconnect)
04253         {
04254           CONNECTION_UNLOCK (connection);            
04255           
04256           _dbus_verbose ("Exiting on Disconnected signal\n");
04257           _dbus_exit (1);
04258           _dbus_assert_not_reached ("Call to exit() returned");
04259         }
04260     }
04261   
04262   /* We drop the lock */
04263   CONNECTION_UNLOCK (connection);
04264   
04265   if (changed && function)
04266     {
04267       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04268                      connection, new_status,
04269                      DISPATCH_STATUS_NAME (new_status));
04270       (* function) (connection, new_status, data);      
04271     }
04272   
04273   dbus_connection_unref (connection);
04274 }
04275 
04301 DBusDispatchStatus
04302 dbus_connection_get_dispatch_status (DBusConnection *connection)
04303 {
04304   DBusDispatchStatus status;
04305 
04306   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04307 
04308   _dbus_verbose ("start\n");
04309   
04310   CONNECTION_LOCK (connection);
04311 
04312   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04313   
04314   CONNECTION_UNLOCK (connection);
04315 
04316   return status;
04317 }
04318 
04322 static DBusHandlerResult
04323 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04324                                                  DBusMessage    *message)
04325 {
04326   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04327     {
04328       /* This means we're letting the bus route this message */
04329       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04330     }
04331   else if (dbus_message_is_method_call (message,
04332                                         DBUS_INTERFACE_PEER,
04333                                         "Ping"))
04334     {
04335       DBusMessage *ret;
04336       dbus_bool_t sent;
04337       
04338       ret = dbus_message_new_method_return (message);
04339       if (ret == NULL)
04340         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04341      
04342       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04343 
04344       dbus_message_unref (ret);
04345 
04346       if (!sent)
04347         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04348       
04349       return DBUS_HANDLER_RESULT_HANDLED;
04350     }
04351   else if (dbus_message_is_method_call (message,
04352                                         DBUS_INTERFACE_PEER,
04353                                         "GetMachineId"))
04354     {
04355       DBusMessage *ret;
04356       dbus_bool_t sent;
04357       DBusString uuid;
04358       
04359       ret = dbus_message_new_method_return (message);
04360       if (ret == NULL)
04361         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04362 
04363       sent = FALSE;
04364       _dbus_string_init (&uuid);
04365       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04366         {
04367           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04368           if (dbus_message_append_args (ret,
04369                                         DBUS_TYPE_STRING, &v_STRING,
04370                                         DBUS_TYPE_INVALID))
04371             {
04372               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04373             }
04374         }
04375       _dbus_string_free (&uuid);
04376       
04377       dbus_message_unref (ret);
04378 
04379       if (!sent)
04380         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04381       
04382       return DBUS_HANDLER_RESULT_HANDLED;
04383     }
04384   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04385     {
04386       /* We need to bounce anything else with this interface, otherwise apps
04387        * could start extending the interface and when we added extensions
04388        * here to DBusConnection we'd break those apps.
04389        */
04390       
04391       DBusMessage *ret;
04392       dbus_bool_t sent;
04393       
04394       ret = dbus_message_new_error (message,
04395                                     DBUS_ERROR_UNKNOWN_METHOD,
04396                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04397       if (ret == NULL)
04398         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04399       
04400       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04401       
04402       dbus_message_unref (ret);
04403       
04404       if (!sent)
04405         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04406       
04407       return DBUS_HANDLER_RESULT_HANDLED;
04408     }
04409   else
04410     {
04411       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04412     }
04413 }
04414 
04421 static DBusHandlerResult
04422 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04423                                                            DBusMessage    *message)
04424 {
04425   /* We just run one filter for now but have the option to run more
04426      if the spec calls for it in the future */
04427 
04428   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04429 }
04430 
04473 DBusDispatchStatus
04474 dbus_connection_dispatch (DBusConnection *connection)
04475 {
04476   DBusMessage *message;
04477   DBusList *link, *filter_list_copy, *message_link;
04478   DBusHandlerResult result;
04479   DBusPendingCall *pending;
04480   dbus_int32_t reply_serial;
04481   DBusDispatchStatus status;
04482 
04483   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04484 
04485   _dbus_verbose ("\n");
04486   
04487   CONNECTION_LOCK (connection);
04488   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04489   if (status != DBUS_DISPATCH_DATA_REMAINS)
04490     {
04491       /* unlocks and calls out to user code */
04492       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04493       return status;
04494     }
04495   
04496   /* We need to ref the connection since the callback could potentially
04497    * drop the last ref to it
04498    */
04499   _dbus_connection_ref_unlocked (connection);
04500 
04501   _dbus_connection_acquire_dispatch (connection);
04502   HAVE_LOCK_CHECK (connection);
04503 
04504   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04505   if (message_link == NULL)
04506     {
04507       /* another thread dispatched our stuff */
04508 
04509       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04510       
04511       _dbus_connection_release_dispatch (connection);
04512 
04513       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04514 
04515       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04516       
04517       dbus_connection_unref (connection);
04518       
04519       return status;
04520     }
04521 
04522   message = message_link->data;
04523 
04524   _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04525                  message,
04526                  dbus_message_type_to_string (dbus_message_get_type (message)),
04527                  dbus_message_get_interface (message) ?
04528                  dbus_message_get_interface (message) :
04529                  "no interface",
04530                  dbus_message_get_member (message) ?
04531                  dbus_message_get_member (message) :
04532                  "no member",
04533                  dbus_message_get_signature (message));
04534 
04535   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04536   
04537   /* Pending call handling must be first, because if you do
04538    * dbus_connection_send_with_reply_and_block() or
04539    * dbus_pending_call_block() then no handlers/filters will be run on
04540    * the reply. We want consistent semantics in the case where we
04541    * dbus_connection_dispatch() the reply.
04542    */
04543   
04544   reply_serial = dbus_message_get_reply_serial (message);
04545   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04546                                          reply_serial);
04547   if (pending)
04548     {
04549       _dbus_verbose ("Dispatching a pending reply\n");
04550       complete_pending_call_and_unlock (connection, pending, message);
04551       pending = NULL; /* it's probably unref'd */
04552       
04553       CONNECTION_LOCK (connection);
04554       _dbus_verbose ("pending call completed in dispatch\n");
04555       result = DBUS_HANDLER_RESULT_HANDLED;
04556       goto out;
04557     }
04558 
04559   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04560   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04561     goto out;
04562  
04563   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04564     {
04565       _dbus_connection_release_dispatch (connection);
04566       HAVE_LOCK_CHECK (connection);
04567       
04568       _dbus_connection_failed_pop (connection, message_link);
04569 
04570       /* unlocks and calls user code */
04571       _dbus_connection_update_dispatch_status_and_unlock (connection,
04572                                                           DBUS_DISPATCH_NEED_MEMORY);
04573       dbus_connection_unref (connection);
04574       
04575       return DBUS_DISPATCH_NEED_MEMORY;
04576     }
04577   
04578   _dbus_list_foreach (&filter_list_copy,
04579                       (DBusForeachFunction)_dbus_message_filter_ref,
04580                       NULL);
04581 
04582   /* We're still protected from dispatch() reentrancy here
04583    * since we acquired the dispatcher
04584    */
04585   CONNECTION_UNLOCK (connection);
04586   
04587   link = _dbus_list_get_first_link (&filter_list_copy);
04588   while (link != NULL)
04589     {
04590       DBusMessageFilter *filter = link->data;
04591       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04592 
04593       if (filter->function == NULL)
04594         {
04595           _dbus_verbose ("  filter was removed in a callback function\n");
04596           link = next;
04597           continue;
04598         }
04599 
04600       _dbus_verbose ("  running filter on message %p\n", message);
04601       result = (* filter->function) (connection, message, filter->user_data);
04602 
04603       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04604         break;
04605 
04606       link = next;
04607     }
04608 
04609   _dbus_list_foreach (&filter_list_copy,
04610                       (DBusForeachFunction)_dbus_message_filter_unref,
04611                       NULL);
04612   _dbus_list_clear (&filter_list_copy);
04613   
04614   CONNECTION_LOCK (connection);
04615 
04616   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04617     {
04618       _dbus_verbose ("No memory\n");
04619       goto out;
04620     }
04621   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04622     {
04623       _dbus_verbose ("filter handled message in dispatch\n");
04624       goto out;
04625     }
04626 
04627   /* We're still protected from dispatch() reentrancy here
04628    * since we acquired the dispatcher
04629    */
04630   _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
04631                  message,
04632                  dbus_message_type_to_string (dbus_message_get_type (message)),
04633                  dbus_message_get_interface (message) ?
04634                  dbus_message_get_interface (message) :
04635                  "no interface",
04636                  dbus_message_get_member (message) ?
04637                  dbus_message_get_member (message) :
04638                  "no member",
04639                  dbus_message_get_signature (message));
04640 
04641   HAVE_LOCK_CHECK (connection);
04642   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04643                                                   message);
04644   
04645   CONNECTION_LOCK (connection);
04646 
04647   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04648     {
04649       _dbus_verbose ("object tree handled message in dispatch\n");
04650       goto out;
04651     }
04652 
04653   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04654     {
04655       DBusMessage *reply;
04656       DBusString str;
04657       DBusPreallocatedSend *preallocated;
04658 
04659       _dbus_verbose ("  sending error %s\n",
04660                      DBUS_ERROR_UNKNOWN_METHOD);
04661       
04662       if (!_dbus_string_init (&str))
04663         {
04664           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04665           _dbus_verbose ("no memory for error string in dispatch\n");
04666           goto out;
04667         }
04668               
04669       if (!_dbus_string_append_printf (&str,
04670                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04671                                        dbus_message_get_member (message),
04672                                        dbus_message_get_signature (message),
04673                                        dbus_message_get_interface (message)))
04674         {
04675           _dbus_string_free (&str);
04676           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04677           _dbus_verbose ("no memory for error string in dispatch\n");
04678           goto out;
04679         }
04680       
04681       reply = dbus_message_new_error (message,
04682                                       DBUS_ERROR_UNKNOWN_METHOD,
04683                                       _dbus_string_get_const_data (&str));
04684       _dbus_string_free (&str);
04685 
04686       if (reply == NULL)
04687         {
04688           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04689           _dbus_verbose ("no memory for error reply in dispatch\n");
04690           goto out;
04691         }
04692       
04693       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04694 
04695       if (preallocated == NULL)
04696         {
04697           dbus_message_unref (reply);
04698           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04699           _dbus_verbose ("no memory for error send in dispatch\n");
04700           goto out;
04701         }
04702 
04703       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04704                                                              reply, NULL);
04705 
04706       dbus_message_unref (reply);
04707       
04708       result = DBUS_HANDLER_RESULT_HANDLED;
04709     }
04710   
04711   _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04712                  dbus_message_type_to_string (dbus_message_get_type (message)),
04713                  dbus_message_get_interface (message) ?
04714                  dbus_message_get_interface (message) :
04715                  "no interface",
04716                  dbus_message_get_member (message) ?
04717                  dbus_message_get_member (message) :
04718                  "no member",
04719                  dbus_message_get_signature (message),
04720                  connection);
04721   
04722  out:
04723   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04724     {
04725       _dbus_verbose ("out of memory\n");
04726       
04727       /* Put message back, and we'll start over.
04728        * Yes this means handlers must be idempotent if they
04729        * don't return HANDLED; c'est la vie.
04730        */
04731       _dbus_connection_putback_message_link_unlocked (connection,
04732                                                       message_link);
04733     }
04734   else
04735     {
04736       _dbus_verbose (" ... done dispatching\n");
04737       
04738       _dbus_list_free_link (message_link);
04739       dbus_message_unref (message); /* don't want the message to count in max message limits
04740                                      * in computing dispatch status below
04741                                      */
04742     }
04743   
04744   _dbus_connection_release_dispatch (connection);
04745   HAVE_LOCK_CHECK (connection);
04746 
04747   _dbus_verbose ("before final status update\n");
04748   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04749 
04750   /* unlocks and calls user code */
04751   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04752   
04753   dbus_connection_unref (connection);
04754   
04755   return status;
04756 }
04757 
04819 dbus_bool_t
04820 dbus_connection_set_watch_functions (DBusConnection              *connection,
04821                                      DBusAddWatchFunction         add_function,
04822                                      DBusRemoveWatchFunction      remove_function,
04823                                      DBusWatchToggledFunction     toggled_function,
04824                                      void                        *data,
04825                                      DBusFreeFunction             free_data_function)
04826 {
04827   dbus_bool_t retval;
04828 
04829   _dbus_return_val_if_fail (connection != NULL, FALSE);
04830   
04831   CONNECTION_LOCK (connection);
04832 
04833   retval = _dbus_watch_list_set_functions (connection->watches,
04834                                            add_function, remove_function,
04835                                            toggled_function,
04836                                            data, free_data_function);
04837 
04838   CONNECTION_UNLOCK (connection);
04839 
04840   return retval;
04841 }
04842 
04882 dbus_bool_t
04883 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04884                                          DBusAddTimeoutFunction     add_function,
04885                                          DBusRemoveTimeoutFunction  remove_function,
04886                                          DBusTimeoutToggledFunction toggled_function,
04887                                          void                      *data,
04888                                          DBusFreeFunction           free_data_function)
04889 {
04890   dbus_bool_t retval;
04891 
04892   _dbus_return_val_if_fail (connection != NULL, FALSE);
04893   
04894   CONNECTION_LOCK (connection);
04895 
04896   retval = _dbus_timeout_list_set_functions (connection->timeouts,
04897                                              add_function, remove_function,
04898                                              toggled_function,
04899                                              data, free_data_function);
04900 
04901   CONNECTION_UNLOCK (connection);
04902 
04903   return retval;
04904 }
04905 
04920 void
04921 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04922                                           DBusWakeupMainFunction     wakeup_main_function,
04923                                           void                      *data,
04924                                           DBusFreeFunction           free_data_function)
04925 {
04926   void *old_data;
04927   DBusFreeFunction old_free_data;
04928 
04929   _dbus_return_if_fail (connection != NULL);
04930   
04931   CONNECTION_LOCK (connection);
04932   old_data = connection->wakeup_main_data;
04933   old_free_data = connection->free_wakeup_main_data;
04934 
04935   connection->wakeup_main_function = wakeup_main_function;
04936   connection->wakeup_main_data = data;
04937   connection->free_wakeup_main_data = free_data_function;
04938   
04939   CONNECTION_UNLOCK (connection);
04940 
04941   /* Callback outside the lock */
04942   if (old_free_data)
04943     (*old_free_data) (old_data);
04944 }
04945 
04966 void
04967 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04968                                               DBusDispatchStatusFunction  function,
04969                                               void                       *data,
04970                                               DBusFreeFunction            free_data_function)
04971 {
04972   void *old_data;
04973   DBusFreeFunction old_free_data;
04974 
04975   _dbus_return_if_fail (connection != NULL);
04976   
04977   CONNECTION_LOCK (connection);
04978   old_data = connection->dispatch_status_data;
04979   old_free_data = connection->free_dispatch_status_data;
04980 
04981   connection->dispatch_status_function = function;
04982   connection->dispatch_status_data = data;
04983   connection->free_dispatch_status_data = free_data_function;
04984   
04985   CONNECTION_UNLOCK (connection);
04986 
04987   /* Callback outside the lock */
04988   if (old_free_data)
04989     (*old_free_data) (old_data);
04990 }
04991 
05011 dbus_bool_t
05012 dbus_connection_get_unix_fd (DBusConnection *connection,
05013                              int            *fd)
05014 {
05015   _dbus_return_val_if_fail (connection != NULL, FALSE);
05016   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05017 
05018 #ifdef DBUS_WIN
05019   /* FIXME do this on a lower level */
05020   return FALSE;
05021 #endif
05022   
05023   return dbus_connection_get_socket(connection, fd);
05024 }
05025 
05041 dbus_bool_t
05042 dbus_connection_get_socket(DBusConnection              *connection,
05043                            int                         *fd)
05044 {
05045   dbus_bool_t retval;
05046 
05047   _dbus_return_val_if_fail (connection != NULL, FALSE);
05048   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05049   
05050   CONNECTION_LOCK (connection);
05051   
05052   retval = _dbus_transport_get_socket_fd (connection->transport,
05053                                           fd);
05054 
05055   CONNECTION_UNLOCK (connection);
05056 
05057   return retval;
05058 }
05059 
05060 
05083 dbus_bool_t
05084 dbus_connection_get_unix_user (DBusConnection *connection,
05085                                unsigned long  *uid)
05086 {
05087   dbus_bool_t result;
05088 
05089   _dbus_return_val_if_fail (connection != NULL, FALSE);
05090   _dbus_return_val_if_fail (uid != NULL, FALSE);
05091   
05092   CONNECTION_LOCK (connection);
05093 
05094   if (!_dbus_transport_get_is_authenticated (connection->transport))
05095     result = FALSE;
05096   else
05097     result = _dbus_transport_get_unix_user (connection->transport,
05098                                             uid);
05099 
05100 #ifdef DBUS_WIN
05101   _dbus_assert (!result);
05102 #endif
05103   
05104   CONNECTION_UNLOCK (connection);
05105 
05106   return result;
05107 }
05108 
05119 dbus_bool_t
05120 dbus_connection_get_unix_process_id (DBusConnection *connection,
05121                                      unsigned long  *pid)
05122 {
05123   dbus_bool_t result;
05124 
05125   _dbus_return_val_if_fail (connection != NULL, FALSE);
05126   _dbus_return_val_if_fail (pid != NULL, FALSE);
05127   
05128   CONNECTION_LOCK (connection);
05129 
05130   if (!_dbus_transport_get_is_authenticated (connection->transport))
05131     result = FALSE;
05132   else
05133     result = _dbus_transport_get_unix_process_id (connection->transport,
05134                                                   pid);
05135 
05136   CONNECTION_UNLOCK (connection);
05137 
05138   return result;
05139 }
05140 
05151 dbus_bool_t
05152 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05153                                             void          **data,
05154                                             dbus_int32_t   *data_size)
05155 {
05156   dbus_bool_t result;
05157 
05158   _dbus_return_val_if_fail (connection != NULL, FALSE);
05159   _dbus_return_val_if_fail (data != NULL, FALSE);
05160   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05161   
05162   CONNECTION_LOCK (connection);
05163 
05164   if (!_dbus_transport_get_is_authenticated (connection->transport))
05165     result = FALSE;
05166   else
05167     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05168                                                          data,
05169                                                          data_size);
05170   CONNECTION_UNLOCK (connection);
05171 
05172   return result;
05173 }
05174 
05197 void
05198 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05199                                         DBusAllowUnixUserFunction   function,
05200                                         void                       *data,
05201                                         DBusFreeFunction            free_data_function)
05202 {
05203   void *old_data = NULL;
05204   DBusFreeFunction old_free_function = NULL;
05205 
05206   _dbus_return_if_fail (connection != NULL);
05207   
05208   CONNECTION_LOCK (connection);
05209   _dbus_transport_set_unix_user_function (connection->transport,
05210                                           function, data, free_data_function,
05211                                           &old_data, &old_free_function);
05212   CONNECTION_UNLOCK (connection);
05213 
05214   if (old_free_function != NULL)
05215     (* old_free_function) (old_data);
05216 }
05217 
05249 dbus_bool_t
05250 dbus_connection_get_windows_user (DBusConnection             *connection,
05251                                   char                      **windows_sid_p)
05252 {
05253   dbus_bool_t result;
05254 
05255   _dbus_return_val_if_fail (connection != NULL, FALSE);
05256   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05257   
05258   CONNECTION_LOCK (connection);
05259 
05260   if (!_dbus_transport_get_is_authenticated (connection->transport))
05261     result = FALSE;
05262   else
05263     result = _dbus_transport_get_windows_user (connection->transport,
05264                                                windows_sid_p);
05265 
05266 #ifdef DBUS_UNIX
05267   _dbus_assert (!result);
05268 #endif
05269   
05270   CONNECTION_UNLOCK (connection);
05271 
05272   return result;
05273 }
05274 
05296 void
05297 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05298                                            DBusAllowWindowsUserFunction function,
05299                                            void                        *data,
05300                                            DBusFreeFunction             free_data_function)
05301 {
05302   void *old_data = NULL;
05303   DBusFreeFunction old_free_function = NULL;
05304 
05305   _dbus_return_if_fail (connection != NULL);
05306   
05307   CONNECTION_LOCK (connection);
05308   _dbus_transport_set_windows_user_function (connection->transport,
05309                                              function, data, free_data_function,
05310                                              &old_data, &old_free_function);
05311   CONNECTION_UNLOCK (connection);
05312 
05313   if (old_free_function != NULL)
05314     (* old_free_function) (old_data);
05315 }
05316 
05343 void
05344 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05345                                      dbus_bool_t                 value)
05346 {
05347   _dbus_return_if_fail (connection != NULL);
05348   
05349   CONNECTION_LOCK (connection);
05350   _dbus_transport_set_allow_anonymous (connection->transport, value);
05351   CONNECTION_UNLOCK (connection);
05352 }
05353 
05371 void
05372 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05373                                          dbus_bool_t                 value)
05374 {
05375   _dbus_return_if_fail (connection != NULL);
05376   
05377   CONNECTION_LOCK (connection);
05378   connection->route_peer_messages = TRUE;
05379   CONNECTION_UNLOCK (connection);
05380 }
05381 
05403 dbus_bool_t
05404 dbus_connection_add_filter (DBusConnection            *connection,
05405                             DBusHandleMessageFunction  function,
05406                             void                      *user_data,
05407                             DBusFreeFunction           free_data_function)
05408 {
05409   DBusMessageFilter *filter;
05410   
05411   _dbus_return_val_if_fail (connection != NULL, FALSE);
05412   _dbus_return_val_if_fail (function != NULL, FALSE);
05413 
05414   filter = dbus_new0 (DBusMessageFilter, 1);
05415   if (filter == NULL)
05416     return FALSE;
05417 
05418   filter->refcount.value = 1;
05419   
05420   CONNECTION_LOCK (connection);
05421 
05422   if (!_dbus_list_append (&connection->filter_list,
05423                           filter))
05424     {
05425       _dbus_message_filter_unref (filter);
05426       CONNECTION_UNLOCK (connection);
05427       return FALSE;
05428     }
05429 
05430   /* Fill in filter after all memory allocated,
05431    * so we don't run the free_user_data_function
05432    * if the add_filter() fails
05433    */
05434   
05435   filter->function = function;
05436   filter->user_data = user_data;
05437   filter->free_user_data_function = free_data_function;
05438         
05439   CONNECTION_UNLOCK (connection);
05440   return TRUE;
05441 }
05442 
05455 void
05456 dbus_connection_remove_filter (DBusConnection            *connection,
05457                                DBusHandleMessageFunction  function,
05458                                void                      *user_data)
05459 {
05460   DBusList *link;
05461   DBusMessageFilter *filter;
05462   
05463   _dbus_return_if_fail (connection != NULL);
05464   _dbus_return_if_fail (function != NULL);
05465   
05466   CONNECTION_LOCK (connection);
05467 
05468   filter = NULL;
05469   
05470   link = _dbus_list_get_last_link (&connection->filter_list);
05471   while (link != NULL)
05472     {
05473       filter = link->data;
05474 
05475       if (filter->function == function &&
05476           filter->user_data == user_data)
05477         {
05478           _dbus_list_remove_link (&connection->filter_list, link);
05479           filter->function = NULL;
05480           
05481           break;
05482         }
05483         
05484       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05485       filter = NULL;
05486     }
05487   
05488   CONNECTION_UNLOCK (connection);
05489 
05490 #ifndef DBUS_DISABLE_CHECKS
05491   if (filter == NULL)
05492     {
05493       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05494                                function, user_data);
05495       return;
05496     }
05497 #endif
05498   
05499   /* Call application code */
05500   if (filter->free_user_data_function)
05501     (* filter->free_user_data_function) (filter->user_data);
05502 
05503   filter->free_user_data_function = NULL;
05504   filter->user_data = NULL;
05505   
05506   _dbus_message_filter_unref (filter);
05507 }
05508 
05521 dbus_bool_t
05522 dbus_connection_try_register_object_path (DBusConnection              *connection,
05523                                           const char                  *path,
05524                                           const DBusObjectPathVTable  *vtable,
05525                                           void                        *user_data,
05526                                           DBusError                   *error)
05527 {
05528   char **decomposed_path;
05529   dbus_bool_t retval;
05530   
05531   _dbus_return_val_if_fail (connection != NULL, FALSE);
05532   _dbus_return_val_if_fail (path != NULL, FALSE);
05533   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05534   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05535 
05536   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05537     return FALSE;
05538 
05539   CONNECTION_LOCK (connection);
05540 
05541   retval = _dbus_object_tree_register (connection->objects,
05542                                        FALSE,
05543                                        (const char **) decomposed_path, vtable,
05544                                        user_data, error);
05545 
05546   CONNECTION_UNLOCK (connection);
05547 
05548   dbus_free_string_array (decomposed_path);
05549 
05550   return retval;
05551 }
05552 
05567 dbus_bool_t
05568 dbus_connection_register_object_path (DBusConnection              *connection,
05569                                       const char                  *path,
05570                                       const DBusObjectPathVTable  *vtable,
05571                                       void                        *user_data)
05572 {
05573   char **decomposed_path;
05574   dbus_bool_t retval;
05575   DBusError error = DBUS_ERROR_INIT;
05576 
05577   _dbus_return_val_if_fail (connection != NULL, FALSE);
05578   _dbus_return_val_if_fail (path != NULL, FALSE);
05579   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05580   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05581 
05582   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05583     return FALSE;
05584 
05585   CONNECTION_LOCK (connection);
05586 
05587   retval = _dbus_object_tree_register (connection->objects,
05588                                        FALSE,
05589                                        (const char **) decomposed_path, vtable,
05590                                        user_data, &error);
05591 
05592   CONNECTION_UNLOCK (connection);
05593 
05594   dbus_free_string_array (decomposed_path);
05595 
05596   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05597     {
05598       _dbus_warn ("%s\n", error.message);
05599       dbus_error_free (&error);
05600       return FALSE;
05601     }
05602 
05603   return retval;
05604 }
05605 
05620 dbus_bool_t
05621 dbus_connection_try_register_fallback (DBusConnection              *connection,
05622                                        const char                  *path,
05623                                        const DBusObjectPathVTable  *vtable,
05624                                        void                        *user_data,
05625                                        DBusError                   *error)
05626 {
05627   char **decomposed_path;
05628   dbus_bool_t retval;
05629 
05630   _dbus_return_val_if_fail (connection != NULL, FALSE);
05631   _dbus_return_val_if_fail (path != NULL, FALSE);
05632   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05633   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05634 
05635   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05636     return FALSE;
05637 
05638   CONNECTION_LOCK (connection);
05639 
05640   retval = _dbus_object_tree_register (connection->objects,
05641                                        TRUE,
05642                                        (const char **) decomposed_path, vtable,
05643                                        user_data, error);
05644 
05645   CONNECTION_UNLOCK (connection);
05646 
05647   dbus_free_string_array (decomposed_path);
05648 
05649   return retval;
05650 }
05651 
05668 dbus_bool_t
05669 dbus_connection_register_fallback (DBusConnection              *connection,
05670                                    const char                  *path,
05671                                    const DBusObjectPathVTable  *vtable,
05672                                    void                        *user_data)
05673 {
05674   char **decomposed_path;
05675   dbus_bool_t retval;
05676   DBusError error = DBUS_ERROR_INIT;
05677 
05678   _dbus_return_val_if_fail (connection != NULL, FALSE);
05679   _dbus_return_val_if_fail (path != NULL, FALSE);
05680   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05681   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05682 
05683   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05684     return FALSE;
05685 
05686   CONNECTION_LOCK (connection);
05687 
05688   retval = _dbus_object_tree_register (connection->objects,
05689                                        TRUE,
05690                                        (const char **) decomposed_path, vtable,
05691                                        user_data, &error);
05692 
05693   CONNECTION_UNLOCK (connection);
05694 
05695   dbus_free_string_array (decomposed_path);
05696 
05697   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05698     {
05699       _dbus_warn ("%s\n", error.message);
05700       dbus_error_free (&error);
05701       return FALSE;
05702     }
05703 
05704   return retval;
05705 }
05706 
05716 dbus_bool_t
05717 dbus_connection_unregister_object_path (DBusConnection              *connection,
05718                                         const char                  *path)
05719 {
05720   char **decomposed_path;
05721 
05722   _dbus_return_val_if_fail (connection != NULL, FALSE);
05723   _dbus_return_val_if_fail (path != NULL, FALSE);
05724   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05725 
05726   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05727       return FALSE;
05728 
05729   CONNECTION_LOCK (connection);
05730 
05731   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05732 
05733   dbus_free_string_array (decomposed_path);
05734 
05735   return TRUE;
05736 }
05737 
05748 dbus_bool_t
05749 dbus_connection_get_object_path_data (DBusConnection *connection,
05750                                       const char     *path,
05751                                       void          **data_p)
05752 {
05753   char **decomposed_path;
05754 
05755   _dbus_return_val_if_fail (connection != NULL, FALSE);
05756   _dbus_return_val_if_fail (path != NULL, FALSE);
05757   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05758 
05759   *data_p = NULL;
05760   
05761   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05762     return FALSE;
05763   
05764   CONNECTION_LOCK (connection);
05765 
05766   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05767 
05768   CONNECTION_UNLOCK (connection);
05769 
05770   dbus_free_string_array (decomposed_path);
05771 
05772   return TRUE;
05773 }
05774 
05785 dbus_bool_t
05786 dbus_connection_list_registered (DBusConnection              *connection,
05787                                  const char                  *parent_path,
05788                                  char                      ***child_entries)
05789 {
05790   char **decomposed_path;
05791   dbus_bool_t retval;
05792   _dbus_return_val_if_fail (connection != NULL, FALSE);
05793   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05794   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05795   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05796 
05797   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05798     return FALSE;
05799 
05800   CONNECTION_LOCK (connection);
05801 
05802   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05803                                                          (const char **) decomposed_path,
05804                                                          child_entries);
05805   dbus_free_string_array (decomposed_path);
05806 
05807   return retval;
05808 }
05809 
05810 static DBusDataSlotAllocator slot_allocator;
05811 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05812 
05827 dbus_bool_t
05828 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05829 {
05830   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05831                                           &_DBUS_LOCK_NAME (connection_slots),
05832                                           slot_p);
05833 }
05834 
05846 void
05847 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05848 {
05849   _dbus_return_if_fail (*slot_p >= 0);
05850   
05851   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05852 }
05853 
05876 dbus_bool_t
05877 dbus_connection_set_data (DBusConnection   *connection,
05878                           dbus_int32_t      slot,
05879                           void             *data,
05880                           DBusFreeFunction  free_data_func)
05881 {
05882   DBusFreeFunction old_free_func;
05883   void *old_data;
05884   dbus_bool_t retval;
05885 
05886   _dbus_return_val_if_fail (connection != NULL, FALSE);
05887   _dbus_return_val_if_fail (slot >= 0, FALSE);
05888   
05889   SLOTS_LOCK (connection);
05890 
05891   retval = _dbus_data_slot_list_set (&slot_allocator,
05892                                      &connection->slot_list,
05893                                      slot, data, free_data_func,
05894                                      &old_free_func, &old_data);
05895   
05896   SLOTS_UNLOCK (connection);
05897 
05898   if (retval)
05899     {
05900       /* Do the actual free outside the connection lock */
05901       if (old_free_func)
05902         (* old_free_func) (old_data);
05903     }
05904 
05905   return retval;
05906 }
05907 
05925 void*
05926 dbus_connection_get_data (DBusConnection   *connection,
05927                           dbus_int32_t      slot)
05928 {
05929   void *res;
05930 
05931   _dbus_return_val_if_fail (connection != NULL, NULL);
05932   
05933   SLOTS_LOCK (connection);
05934 
05935   res = _dbus_data_slot_list_get (&slot_allocator,
05936                                   &connection->slot_list,
05937                                   slot);
05938   
05939   SLOTS_UNLOCK (connection);
05940 
05941   return res;
05942 }
05943 
05950 void
05951 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05952 {  
05953   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05954 }
05955 
05964 void
05965 dbus_connection_set_max_message_size (DBusConnection *connection,
05966                                       long            size)
05967 {
05968   _dbus_return_if_fail (connection != NULL);
05969   
05970   CONNECTION_LOCK (connection);
05971   _dbus_transport_set_max_message_size (connection->transport,
05972                                         size);
05973   CONNECTION_UNLOCK (connection);
05974 }
05975 
05982 long
05983 dbus_connection_get_max_message_size (DBusConnection *connection)
05984 {
05985   long res;
05986 
05987   _dbus_return_val_if_fail (connection != NULL, 0);
05988   
05989   CONNECTION_LOCK (connection);
05990   res = _dbus_transport_get_max_message_size (connection->transport);
05991   CONNECTION_UNLOCK (connection);
05992   return res;
05993 }
05994 
06003 void
06004 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06005                                           long            n)
06006 {
06007   _dbus_return_if_fail (connection != NULL);
06008 
06009   CONNECTION_LOCK (connection);
06010   _dbus_transport_set_max_message_unix_fds (connection->transport,
06011                                             n);
06012   CONNECTION_UNLOCK (connection);
06013 }
06014 
06021 long
06022 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06023 {
06024   long res;
06025 
06026   _dbus_return_val_if_fail (connection != NULL, 0);
06027 
06028   CONNECTION_LOCK (connection);
06029   res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06030   CONNECTION_UNLOCK (connection);
06031   return res;
06032 }
06033 
06059 void
06060 dbus_connection_set_max_received_size (DBusConnection *connection,
06061                                        long            size)
06062 {
06063   _dbus_return_if_fail (connection != NULL);
06064   
06065   CONNECTION_LOCK (connection);
06066   _dbus_transport_set_max_received_size (connection->transport,
06067                                          size);
06068   CONNECTION_UNLOCK (connection);
06069 }
06070 
06077 long
06078 dbus_connection_get_max_received_size (DBusConnection *connection)
06079 {
06080   long res;
06081 
06082   _dbus_return_val_if_fail (connection != NULL, 0);
06083   
06084   CONNECTION_LOCK (connection);
06085   res = _dbus_transport_get_max_received_size (connection->transport);
06086   CONNECTION_UNLOCK (connection);
06087   return res;
06088 }
06089 
06101 void
06102 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06103                                            long            n)
06104 {
06105   _dbus_return_if_fail (connection != NULL);
06106 
06107   CONNECTION_LOCK (connection);
06108   _dbus_transport_set_max_received_unix_fds (connection->transport,
06109                                              n);
06110   CONNECTION_UNLOCK (connection);
06111 }
06112 
06119 long
06120 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06121 {
06122   long res;
06123 
06124   _dbus_return_val_if_fail (connection != NULL, 0);
06125 
06126   CONNECTION_LOCK (connection);
06127   res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06128   CONNECTION_UNLOCK (connection);
06129   return res;
06130 }
06131 
06142 long
06143 dbus_connection_get_outgoing_size (DBusConnection *connection)
06144 {
06145   long res;
06146 
06147   _dbus_return_val_if_fail (connection != NULL, 0);
06148 
06149   CONNECTION_LOCK (connection);
06150   res = _dbus_counter_get_size_value (connection->outgoing_counter);
06151   CONNECTION_UNLOCK (connection);
06152   return res;
06153 }
06154 
06162 long
06163 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06164 {
06165   long res;
06166 
06167   _dbus_return_val_if_fail (connection != NULL, 0);
06168 
06169   CONNECTION_LOCK (connection);
06170   res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06171   CONNECTION_UNLOCK (connection);
06172   return res;
06173 }
06174