• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

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) _dbus_connection_unlock (connection)
00073 
00074 #define SLOTS_LOCK(connection) do {                     \
00075     _dbus_mutex_lock ((connection)->slot_mutex);        \
00076   } while (0)
00077 
00078 #define SLOTS_UNLOCK(connection) do {                   \
00079     _dbus_mutex_unlock ((connection)->slot_mutex);      \
00080   } while (0)
00081 
00082 #define DISPATCH_STATUS_NAME(s)                                            \
00083                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00084                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00085                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00086                       "???")
00087 
00208 typedef struct DBusMessageFilter DBusMessageFilter;
00209 
00213 struct DBusMessageFilter
00214 {
00215   DBusAtomic refcount; 
00216   DBusHandleMessageFunction function; 
00217   void *user_data; 
00218   DBusFreeFunction free_user_data_function; 
00219 };
00220 
00221 
00225 struct DBusPreallocatedSend
00226 {
00227   DBusConnection *connection; 
00228   DBusList *queue_link;       
00229   DBusList *counter_link;     
00230 };
00231 
00232 #if HAVE_DECL_MSG_NOSIGNAL
00233 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00234 #else
00235 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00236 #endif
00237 
00241 struct DBusConnection
00242 {
00243   DBusAtomic refcount; 
00245   DBusMutex *mutex; 
00247   DBusMutex *dispatch_mutex;     
00248   DBusCondVar *dispatch_cond;    
00249   DBusMutex *io_path_mutex;      
00250   DBusCondVar *io_path_cond;     
00252   DBusList *outgoing_messages; 
00253   DBusList *incoming_messages; 
00254   DBusList *expired_messages;  
00256   DBusMessage *message_borrowed; 
00260   int n_outgoing;              
00261   int n_incoming;              
00263   DBusCounter *outgoing_counter; 
00265   DBusTransport *transport;    
00266   DBusWatchList *watches;      
00267   DBusTimeoutList *timeouts;   
00269   DBusList *filter_list;        
00271   DBusMutex *slot_mutex;        
00272   DBusDataSlotList slot_list;   
00274   DBusHashTable *pending_replies;  
00276   dbus_uint32_t client_serial;       
00277   DBusList *disconnect_message_link; 
00279   DBusWakeupMainFunction wakeup_main_function; 
00280   void *wakeup_main_data; 
00281   DBusFreeFunction free_wakeup_main_data; 
00283   DBusDispatchStatusFunction dispatch_status_function; 
00284   void *dispatch_status_data; 
00285   DBusFreeFunction free_dispatch_status_data; 
00287   DBusDispatchStatus last_dispatch_status; 
00289   DBusObjectTree *objects; 
00291   char *server_guid; 
00293   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00294    * from connection->mutex and all bitfields in a word have to be read/written together.
00295    * So you can't have a different lock for different bitfields in the same word.
00296    */
00297   dbus_bool_t dispatch_acquired; 
00298   dbus_bool_t io_path_acquired;  
00300   unsigned int shareable : 1; 
00302   unsigned int exit_on_disconnect : 1; 
00304   unsigned int route_peer_messages : 1; 
00306   unsigned int disconnected_message_arrived : 1;   
00310   unsigned int disconnected_message_processed : 1; 
00314 #ifndef DBUS_DISABLE_CHECKS
00315   unsigned int have_connection_lock : 1; 
00316 #endif
00317   
00318 #ifndef DBUS_DISABLE_CHECKS
00319   int generation; 
00320 #endif 
00321 };
00322 
00323 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00324 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00325                                                                               DBusDispatchStatus  new_status);
00326 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00327 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00328 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00329 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00330 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00331 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00332 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
00333                                                                               dbus_uint32_t       client_serial);
00334 
00335 static DBusMessageFilter *
00336 _dbus_message_filter_ref (DBusMessageFilter *filter)
00337 {
00338 #ifdef DBUS_DISABLE_ASSERT
00339   _dbus_atomic_inc (&filter->refcount);
00340 #else
00341   dbus_int32_t old_value;
00342 
00343   old_value = _dbus_atomic_inc (&filter->refcount);
00344   _dbus_assert (old_value > 0);
00345 #endif
00346 
00347   return filter;
00348 }
00349 
00350 static void
00351 _dbus_message_filter_unref (DBusMessageFilter *filter)
00352 {
00353   dbus_int32_t old_value;
00354 
00355   old_value = _dbus_atomic_dec (&filter->refcount);
00356   _dbus_assert (old_value > 0);
00357 
00358   if (old_value == 1)
00359     {
00360       if (filter->free_user_data_function)
00361         (* filter->free_user_data_function) (filter->user_data);
00362       
00363       dbus_free (filter);
00364     }
00365 }
00366 
00372 void
00373 _dbus_connection_lock (DBusConnection *connection)
00374 {
00375   CONNECTION_LOCK (connection);
00376 }
00377 
00383 void
00384 _dbus_connection_unlock (DBusConnection *connection)
00385 {
00386   DBusList *expired_messages;
00387   DBusList *iter;
00388 
00389   if (TRACE_LOCKS)
00390     {
00391       _dbus_verbose ("UNLOCK\n");
00392     }
00393 
00394   /* If we had messages that expired (fell off the incoming or outgoing
00395    * queues) while we were locked, actually release them now */
00396   expired_messages = connection->expired_messages;
00397   connection->expired_messages = NULL;
00398 
00399   RELEASING_LOCK_CHECK (connection);
00400   _dbus_mutex_unlock (connection->mutex);
00401 
00402   for (iter = _dbus_list_pop_first_link (&expired_messages);
00403       iter != NULL;
00404       iter = _dbus_list_pop_first_link (&expired_messages))
00405     {
00406       DBusMessage *message = iter->data;
00407 
00408       dbus_message_unref (message);
00409       _dbus_list_free_link (iter);
00410     }
00411 }
00412 
00420 static void
00421 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00422 {
00423   if (connection->wakeup_main_function)
00424     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00425 }
00426 
00427 #ifdef DBUS_BUILD_TESTS
00428 /* For now this function isn't used */
00438 dbus_bool_t
00439 _dbus_connection_queue_received_message (DBusConnection *connection,
00440                                          DBusMessage    *message)
00441 {
00442   DBusList *link;
00443 
00444   link = _dbus_list_alloc_link (message);
00445   if (link == NULL)
00446     return FALSE;
00447 
00448   dbus_message_ref (message);
00449   _dbus_connection_queue_received_message_link (connection, link);
00450 
00451   return TRUE;
00452 }
00453 
00466 void 
00467 _dbus_connection_test_get_locks (DBusConnection *connection,
00468                                  DBusMutex     **mutex_loc,
00469                                  DBusMutex     **dispatch_mutex_loc,
00470                                  DBusMutex     **io_path_mutex_loc,
00471                                  DBusCondVar   **dispatch_cond_loc,
00472                                  DBusCondVar   **io_path_cond_loc)
00473 {
00474   *mutex_loc = connection->mutex;
00475   *dispatch_mutex_loc = connection->dispatch_mutex;
00476   *io_path_mutex_loc = connection->io_path_mutex; 
00477   *dispatch_cond_loc = connection->dispatch_cond;
00478   *io_path_cond_loc = connection->io_path_cond;
00479 }
00480 #endif
00481 
00490 void
00491 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00492                                               DBusList        *link)
00493 {
00494   DBusPendingCall *pending;
00495   dbus_uint32_t reply_serial;
00496   DBusMessage *message;
00497   
00498   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00499   
00500   _dbus_list_append_link (&connection->incoming_messages,
00501                           link);
00502   message = link->data;
00503 
00504   /* If this is a reply we're waiting on, remove timeout for it */
00505   reply_serial = dbus_message_get_reply_serial (message);
00506   if (reply_serial != 0)
00507     {
00508       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00509                                              reply_serial);
00510       if (pending != NULL)
00511         {
00512           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00513             _dbus_connection_remove_timeout_unlocked (connection,
00514                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00515 
00516           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00517         }
00518     }
00519   
00520   
00521 
00522   connection->n_incoming += 1;
00523 
00524   _dbus_connection_wakeup_mainloop (connection);
00525   
00526   _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00527                  message,
00528                  dbus_message_type_to_string (dbus_message_get_type (message)),
00529                  dbus_message_get_path (message) ?
00530                  dbus_message_get_path (message) :
00531                  "no path",
00532                  dbus_message_get_interface (message) ?
00533                  dbus_message_get_interface (message) :
00534                  "no interface",
00535                  dbus_message_get_member (message) ?
00536                  dbus_message_get_member (message) :
00537                  "no member",
00538                  dbus_message_get_signature (message),
00539                  dbus_message_get_reply_serial (message),
00540                  connection,
00541                  connection->n_incoming);}
00542 
00551 void
00552 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00553                                                  DBusList *link)
00554 {
00555   HAVE_LOCK_CHECK (connection);
00556   
00557   _dbus_list_append_link (&connection->incoming_messages, link);
00558 
00559   connection->n_incoming += 1;
00560 
00561   _dbus_connection_wakeup_mainloop (connection);
00562   
00563   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00564                  link->data, connection, connection->n_incoming);
00565 }
00566 
00567 
00575 dbus_bool_t
00576 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00577 {
00578   HAVE_LOCK_CHECK (connection);
00579   return connection->outgoing_messages != NULL;
00580 }
00581 
00591 dbus_bool_t
00592 dbus_connection_has_messages_to_send (DBusConnection *connection)
00593 {
00594   dbus_bool_t v;
00595   
00596   _dbus_return_val_if_fail (connection != NULL, FALSE);
00597 
00598   CONNECTION_LOCK (connection);
00599   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00600   CONNECTION_UNLOCK (connection);
00601 
00602   return v;
00603 }
00604 
00612 DBusMessage*
00613 _dbus_connection_get_message_to_send (DBusConnection *connection)
00614 {
00615   HAVE_LOCK_CHECK (connection);
00616   
00617   return _dbus_list_get_last (&connection->outgoing_messages);
00618 }
00619 
00628 void
00629 _dbus_connection_message_sent_unlocked (DBusConnection *connection,
00630                                         DBusMessage    *message)
00631 {
00632   DBusList *link;
00633 
00634   HAVE_LOCK_CHECK (connection);
00635   
00636   /* This can be called before we even complete authentication, since
00637    * it's called on disconnect to clean up the outgoing queue.
00638    * It's also called as we successfully send each message.
00639    */
00640   
00641   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00642   _dbus_assert (link != NULL);
00643   _dbus_assert (link->data == message);
00644 
00645   _dbus_list_unlink (&connection->outgoing_messages,
00646                      link);
00647   _dbus_list_prepend_link (&connection->expired_messages, link);
00648 
00649   connection->n_outgoing -= 1;
00650 
00651   _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00652                  message,
00653                  dbus_message_type_to_string (dbus_message_get_type (message)),
00654                  dbus_message_get_path (message) ?
00655                  dbus_message_get_path (message) :
00656                  "no path",
00657                  dbus_message_get_interface (message) ?
00658                  dbus_message_get_interface (message) :
00659                  "no interface",
00660                  dbus_message_get_member (message) ?
00661                  dbus_message_get_member (message) :
00662                  "no member",
00663                  dbus_message_get_signature (message),
00664                  connection, connection->n_outgoing);
00665 
00666   /* It's OK that in principle we call the notify function, because for the
00667    * outgoing limit, there isn't one */
00668   _dbus_message_remove_counter (message, connection->outgoing_counter, NULL);
00669 
00670   /* The message will actually be unreffed when we unlock */
00671 }
00672 
00674 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00675                                                   DBusWatch     *watch);
00677 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00678                                                   DBusWatch     *watch);
00680 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00681                                                   DBusWatch     *watch,
00682                                                   dbus_bool_t    enabled);
00683 
00684 static dbus_bool_t
00685 protected_change_watch (DBusConnection         *connection,
00686                         DBusWatch              *watch,
00687                         DBusWatchAddFunction    add_function,
00688                         DBusWatchRemoveFunction remove_function,
00689                         DBusWatchToggleFunction toggle_function,
00690                         dbus_bool_t             enabled)
00691 {
00692   dbus_bool_t retval;
00693 
00694   HAVE_LOCK_CHECK (connection);
00695 
00696   /* The original purpose of protected_change_watch() was to hold a
00697    * ref on the connection while dropping the connection lock, then
00698    * calling out to the app.  This was a broken hack that did not
00699    * work, since the connection was in a hosed state (no WatchList
00700    * field) while calling out.
00701    *
00702    * So for now we'll just keep the lock while calling out. This means
00703    * apps are not allowed to call DBusConnection methods inside a
00704    * watch function or they will deadlock.
00705    *
00706    * The "real fix" is to use the _and_unlock() pattern found
00707    * elsewhere in the code, to defer calling out to the app until
00708    * we're about to drop locks and return flow of control to the app
00709    * anyway.
00710    *
00711    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00712    */
00713 
00714   if (connection->watches)
00715     {
00716       if (add_function)
00717         retval = (* add_function) (connection->watches, watch);
00718       else if (remove_function)
00719         {
00720           retval = TRUE;
00721           (* remove_function) (connection->watches, watch);
00722         }
00723       else
00724         {
00725           retval = TRUE;
00726           (* toggle_function) (connection->watches, watch, enabled);
00727         }
00728       return retval;
00729     }
00730   else
00731     return FALSE;
00732 }
00733      
00734 
00746 dbus_bool_t
00747 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00748                                      DBusWatch      *watch)
00749 {
00750   return protected_change_watch (connection, watch,
00751                                  _dbus_watch_list_add_watch,
00752                                  NULL, NULL, FALSE);
00753 }
00754 
00764 void
00765 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00766                                         DBusWatch      *watch)
00767 {
00768   protected_change_watch (connection, watch,
00769                           NULL,
00770                           _dbus_watch_list_remove_watch,
00771                           NULL, FALSE);
00772 }
00773 
00784 void
00785 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00786                                         DBusWatch      *watch,
00787                                         dbus_bool_t     enabled)
00788 {
00789   _dbus_assert (watch != NULL);
00790 
00791   protected_change_watch (connection, watch,
00792                           NULL, NULL,
00793                           _dbus_watch_list_toggle_watch,
00794                           enabled);
00795 }
00796 
00798 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00799                                                    DBusTimeout     *timeout);
00801 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00802                                                    DBusTimeout     *timeout);
00804 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00805                                                    DBusTimeout     *timeout,
00806                                                    dbus_bool_t      enabled);
00807 
00808 static dbus_bool_t
00809 protected_change_timeout (DBusConnection           *connection,
00810                           DBusTimeout              *timeout,
00811                           DBusTimeoutAddFunction    add_function,
00812                           DBusTimeoutRemoveFunction remove_function,
00813                           DBusTimeoutToggleFunction toggle_function,
00814                           dbus_bool_t               enabled)
00815 {
00816   dbus_bool_t retval;
00817 
00818   HAVE_LOCK_CHECK (connection);
00819 
00820   /* The original purpose of protected_change_timeout() was to hold a
00821    * ref on the connection while dropping the connection lock, then
00822    * calling out to the app.  This was a broken hack that did not
00823    * work, since the connection was in a hosed state (no TimeoutList
00824    * field) while calling out.
00825    *
00826    * So for now we'll just keep the lock while calling out. This means
00827    * apps are not allowed to call DBusConnection methods inside a
00828    * timeout function or they will deadlock.
00829    *
00830    * The "real fix" is to use the _and_unlock() pattern found
00831    * elsewhere in the code, to defer calling out to the app until
00832    * we're about to drop locks and return flow of control to the app
00833    * anyway.
00834    *
00835    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00836    */
00837 
00838   if (connection->timeouts)
00839     {
00840       if (add_function)
00841         retval = (* add_function) (connection->timeouts, timeout);
00842       else if (remove_function)
00843         {
00844           retval = TRUE;
00845           (* remove_function) (connection->timeouts, timeout);
00846         }
00847       else
00848         {
00849           retval = TRUE;
00850           (* toggle_function) (connection->timeouts, timeout, enabled);
00851         }
00852       return retval;
00853     }
00854   else
00855     return FALSE;
00856 }
00857 
00870 dbus_bool_t
00871 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00872                                        DBusTimeout    *timeout)
00873 {
00874   return protected_change_timeout (connection, timeout,
00875                                    _dbus_timeout_list_add_timeout,
00876                                    NULL, NULL, FALSE);
00877 }
00878 
00888 void
00889 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00890                                           DBusTimeout    *timeout)
00891 {
00892   protected_change_timeout (connection, timeout,
00893                             NULL,
00894                             _dbus_timeout_list_remove_timeout,
00895                             NULL, FALSE);
00896 }
00897 
00908 void
00909 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00910                                           DBusTimeout      *timeout,
00911                                           dbus_bool_t       enabled)
00912 {
00913   protected_change_timeout (connection, timeout,
00914                             NULL, NULL,
00915                             _dbus_timeout_list_toggle_timeout,
00916                             enabled);
00917 }
00918 
00919 static dbus_bool_t
00920 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00921                                                DBusPendingCall *pending)
00922 {
00923   dbus_uint32_t reply_serial;
00924   DBusTimeout *timeout;
00925 
00926   HAVE_LOCK_CHECK (connection);
00927 
00928   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00929 
00930   _dbus_assert (reply_serial != 0);
00931 
00932   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00933 
00934   if (timeout)
00935     {
00936       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00937         return FALSE;
00938       
00939       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00940                                         reply_serial,
00941                                         pending))
00942         {
00943           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00944 
00945           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00946           HAVE_LOCK_CHECK (connection);
00947           return FALSE;
00948         }
00949       
00950       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00951     }
00952   else
00953     {
00954       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00955                                         reply_serial,
00956                                         pending))
00957         {
00958           HAVE_LOCK_CHECK (connection);
00959           return FALSE;
00960         }
00961     }
00962 
00963   _dbus_pending_call_ref_unlocked (pending);
00964 
00965   HAVE_LOCK_CHECK (connection);
00966   
00967   return TRUE;
00968 }
00969 
00970 static void
00971 free_pending_call_on_hash_removal (void *data)
00972 {
00973   DBusPendingCall *pending;
00974   DBusConnection  *connection;
00975   
00976   if (data == NULL)
00977     return;
00978 
00979   pending = data;
00980 
00981   connection = _dbus_pending_call_get_connection_unlocked (pending);
00982 
00983   HAVE_LOCK_CHECK (connection);
00984   
00985   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00986     {
00987       _dbus_connection_remove_timeout_unlocked (connection,
00988                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00989       
00990       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00991     }
00992 
00993   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00994    * here, but the pending call finalizer could in principle call out to 
00995    * application code so we pretty much have to... some larger code reorg 
00996    * might be needed.
00997    */
00998   _dbus_connection_ref_unlocked (connection);
00999   _dbus_pending_call_unref_and_unlock (pending);
01000   CONNECTION_LOCK (connection);
01001   _dbus_connection_unref_unlocked (connection);
01002 }
01003 
01004 static void
01005 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
01006                                                DBusPendingCall *pending)
01007 {
01008   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
01009    * say the least.
01010    */
01011   _dbus_hash_table_remove_int (connection->pending_replies,
01012                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01013 }
01014 
01015 static void
01016 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
01017                                                  DBusPendingCall *pending)
01018 {
01019   /* The idea here is to avoid finalizing the pending call
01020    * with the lock held, since there's a destroy notifier
01021    * in pending call that goes out to application code.
01022    *
01023    * There's an extra unlock inside the hash table
01024    * "free pending call" function FIXME...
01025    */
01026   _dbus_pending_call_ref_unlocked (pending);
01027   _dbus_hash_table_remove_int (connection->pending_replies,
01028                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01029 
01030   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01031       _dbus_connection_remove_timeout_unlocked (connection,
01032               _dbus_pending_call_get_timeout_unlocked (pending));
01033 
01034   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01035 
01036   _dbus_pending_call_unref_and_unlock (pending);
01037 }
01038 
01047 void
01048 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01049                                       DBusPendingCall *pending)
01050 {
01051   CONNECTION_LOCK (connection);
01052   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01053 }
01054 
01064 static dbus_bool_t
01065 _dbus_connection_acquire_io_path (DBusConnection *connection,
01066                                   int             timeout_milliseconds)
01067 {
01068   dbus_bool_t we_acquired;
01069   
01070   HAVE_LOCK_CHECK (connection);
01071 
01072   /* We don't want the connection to vanish */
01073   _dbus_connection_ref_unlocked (connection);
01074 
01075   /* We will only touch io_path_acquired which is protected by our mutex */
01076   CONNECTION_UNLOCK (connection);
01077   
01078   _dbus_verbose ("locking io_path_mutex\n");
01079   _dbus_mutex_lock (connection->io_path_mutex);
01080 
01081   _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01082                  connection->io_path_acquired, timeout_milliseconds);
01083 
01084   we_acquired = FALSE;
01085   
01086   if (connection->io_path_acquired)
01087     {
01088       if (timeout_milliseconds != -1)
01089         {
01090           _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01091                          timeout_milliseconds);
01092 
01093           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01094                                            connection->io_path_mutex,
01095                                            timeout_milliseconds))
01096             {
01097               /* We timed out before anyone signaled. */
01098               /* (writing the loop to handle the !timedout case by
01099                * waiting longer if needed is a pain since dbus
01100                * wraps pthread_cond_timedwait to take a relative
01101                * time instead of absolute, something kind of stupid
01102                * on our part. for now it doesn't matter, we will just
01103                * end up back here eventually.)
01104                */
01105             }
01106         }
01107       else
01108         {
01109           while (connection->io_path_acquired)
01110             {
01111               _dbus_verbose ("waiting for IO path to be acquirable\n");
01112               _dbus_condvar_wait (connection->io_path_cond, 
01113                                   connection->io_path_mutex);
01114             }
01115         }
01116     }
01117   
01118   if (!connection->io_path_acquired)
01119     {
01120       we_acquired = TRUE;
01121       connection->io_path_acquired = TRUE;
01122     }
01123   
01124   _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01125                  connection->io_path_acquired, we_acquired);
01126 
01127   _dbus_verbose ("unlocking io_path_mutex\n");
01128   _dbus_mutex_unlock (connection->io_path_mutex);
01129 
01130   CONNECTION_LOCK (connection);
01131   
01132   HAVE_LOCK_CHECK (connection);
01133 
01134   _dbus_connection_unref_unlocked (connection);
01135   
01136   return we_acquired;
01137 }
01138 
01146 static void
01147 _dbus_connection_release_io_path (DBusConnection *connection)
01148 {
01149   HAVE_LOCK_CHECK (connection);
01150   
01151   _dbus_verbose ("locking io_path_mutex\n");
01152   _dbus_mutex_lock (connection->io_path_mutex);
01153   
01154   _dbus_assert (connection->io_path_acquired);
01155 
01156   _dbus_verbose ("start connection->io_path_acquired = %d\n",
01157                  connection->io_path_acquired);
01158   
01159   connection->io_path_acquired = FALSE;
01160   _dbus_condvar_wake_one (connection->io_path_cond);
01161 
01162   _dbus_verbose ("unlocking io_path_mutex\n");
01163   _dbus_mutex_unlock (connection->io_path_mutex);
01164 }
01165 
01201 void
01202 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01203                                         DBusPendingCall *pending,
01204                                         unsigned int    flags,
01205                                         int             timeout_milliseconds)
01206 {
01207   _dbus_verbose ("start\n");
01208   
01209   HAVE_LOCK_CHECK (connection);
01210   
01211   if (connection->n_outgoing == 0)
01212     flags &= ~DBUS_ITERATION_DO_WRITING;
01213 
01214   if (_dbus_connection_acquire_io_path (connection,
01215                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01216     {
01217       HAVE_LOCK_CHECK (connection);
01218       
01219       if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01220         {
01221           _dbus_verbose ("pending call completed while acquiring I/O path");
01222         }
01223       else if ( (pending != NULL) &&
01224                 _dbus_connection_peek_for_reply_unlocked (connection,
01225                                                           _dbus_pending_call_get_reply_serial_unlocked (pending)))
01226         {
01227           _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01228         }
01229       else
01230         {
01231           _dbus_transport_do_iteration (connection->transport,
01232                                         flags, timeout_milliseconds);
01233         }
01234 
01235       _dbus_connection_release_io_path (connection);
01236     }
01237 
01238   HAVE_LOCK_CHECK (connection);
01239 
01240   _dbus_verbose ("end\n");
01241 }
01242 
01252 DBusConnection*
01253 _dbus_connection_new_for_transport (DBusTransport *transport)
01254 {
01255   DBusConnection *connection;
01256   DBusWatchList *watch_list;
01257   DBusTimeoutList *timeout_list;
01258   DBusHashTable *pending_replies;
01259   DBusList *disconnect_link;
01260   DBusMessage *disconnect_message;
01261   DBusCounter *outgoing_counter;
01262   DBusObjectTree *objects;
01263   
01264   watch_list = NULL;
01265   connection = NULL;
01266   pending_replies = NULL;
01267   timeout_list = NULL;
01268   disconnect_link = NULL;
01269   disconnect_message = NULL;
01270   outgoing_counter = NULL;
01271   objects = NULL;
01272   
01273   watch_list = _dbus_watch_list_new ();
01274   if (watch_list == NULL)
01275     goto error;
01276 
01277   timeout_list = _dbus_timeout_list_new ();
01278   if (timeout_list == NULL)
01279     goto error;  
01280 
01281   pending_replies =
01282     _dbus_hash_table_new (DBUS_HASH_INT,
01283                           NULL,
01284                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01285   if (pending_replies == NULL)
01286     goto error;
01287   
01288   connection = dbus_new0 (DBusConnection, 1);
01289   if (connection == NULL)
01290     goto error;
01291 
01292   _dbus_mutex_new_at_location (&connection->mutex);
01293   if (connection->mutex == NULL)
01294     goto error;
01295 
01296   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01297   if (connection->io_path_mutex == NULL)
01298     goto error;
01299 
01300   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01301   if (connection->dispatch_mutex == NULL)
01302     goto error;
01303   
01304   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01305   if (connection->dispatch_cond == NULL)
01306     goto error;
01307   
01308   _dbus_condvar_new_at_location (&connection->io_path_cond);
01309   if (connection->io_path_cond == NULL)
01310     goto error;
01311 
01312   _dbus_mutex_new_at_location (&connection->slot_mutex);
01313   if (connection->slot_mutex == NULL)
01314     goto error;
01315 
01316   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01317                                                 DBUS_INTERFACE_LOCAL,
01318                                                 "Disconnected");
01319   
01320   if (disconnect_message == NULL)
01321     goto error;
01322 
01323   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01324   if (disconnect_link == NULL)
01325     goto error;
01326 
01327   outgoing_counter = _dbus_counter_new ();
01328   if (outgoing_counter == NULL)
01329     goto error;
01330 
01331   objects = _dbus_object_tree_new (connection);
01332   if (objects == NULL)
01333     goto error;
01334   
01335   if (_dbus_modify_sigpipe)
01336     _dbus_disable_sigpipe ();
01337 
01338   /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
01339   _dbus_atomic_inc (&connection->refcount);
01340   connection->transport = transport;
01341   connection->watches = watch_list;
01342   connection->timeouts = timeout_list;
01343   connection->pending_replies = pending_replies;
01344   connection->outgoing_counter = outgoing_counter;
01345   connection->filter_list = NULL;
01346   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01347   connection->objects = objects;
01348   connection->exit_on_disconnect = FALSE;
01349   connection->shareable = FALSE;
01350   connection->route_peer_messages = FALSE;
01351   connection->disconnected_message_arrived = FALSE;
01352   connection->disconnected_message_processed = FALSE;
01353   
01354 #ifndef DBUS_DISABLE_CHECKS
01355   connection->generation = _dbus_current_generation;
01356 #endif
01357   
01358   _dbus_data_slot_list_init (&connection->slot_list);
01359 
01360   connection->client_serial = 1;
01361 
01362   connection->disconnect_message_link = disconnect_link;
01363 
01364   CONNECTION_LOCK (connection);
01365   
01366   if (!_dbus_transport_set_connection (transport, connection))
01367     {
01368       CONNECTION_UNLOCK (connection);
01369 
01370       goto error;
01371     }
01372 
01373   _dbus_transport_ref (transport);
01374 
01375   CONNECTION_UNLOCK (connection);
01376   
01377   return connection;
01378   
01379  error:
01380   if (disconnect_message != NULL)
01381     dbus_message_unref (disconnect_message);
01382   
01383   if (disconnect_link != NULL)
01384     _dbus_list_free_link (disconnect_link);
01385   
01386   if (connection != NULL)
01387     {
01388       _dbus_condvar_free_at_location (&connection->io_path_cond);
01389       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01390       _dbus_mutex_free_at_location (&connection->mutex);
01391       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01392       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01393       _dbus_mutex_free_at_location (&connection->slot_mutex);
01394       dbus_free (connection);
01395     }
01396   if (pending_replies)
01397     _dbus_hash_table_unref (pending_replies);
01398   
01399   if (watch_list)
01400     _dbus_watch_list_free (watch_list);
01401 
01402   if (timeout_list)
01403     _dbus_timeout_list_free (timeout_list);
01404 
01405   if (outgoing_counter)
01406     _dbus_counter_unref (outgoing_counter);
01407 
01408   if (objects)
01409     _dbus_object_tree_unref (objects);
01410   
01411   return NULL;
01412 }
01413 
01421 DBusConnection *
01422 _dbus_connection_ref_unlocked (DBusConnection *connection)
01423 {  
01424   _dbus_assert (connection != NULL);
01425   _dbus_assert (connection->generation == _dbus_current_generation);
01426 
01427   HAVE_LOCK_CHECK (connection);
01428 
01429   _dbus_atomic_inc (&connection->refcount);
01430 
01431   return connection;
01432 }
01433 
01440 void
01441 _dbus_connection_unref_unlocked (DBusConnection *connection)
01442 {
01443   dbus_bool_t last_unref;
01444 
01445   HAVE_LOCK_CHECK (connection);
01446   
01447   _dbus_assert (connection != NULL);
01448 
01449   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01450 
01451   if (last_unref)
01452     _dbus_connection_last_unref (connection);
01453 }
01454 
01455 static dbus_uint32_t
01456 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01457 {
01458   dbus_uint32_t serial;
01459 
01460   serial = connection->client_serial++;
01461 
01462   if (connection->client_serial == 0)
01463     connection->client_serial = 1;
01464 
01465   return serial;
01466 }
01467 
01481 dbus_bool_t
01482 _dbus_connection_handle_watch (DBusWatch                   *watch,
01483                                unsigned int                 condition,
01484                                void                        *data)
01485 {
01486   DBusConnection *connection;
01487   dbus_bool_t retval;
01488   DBusDispatchStatus status;
01489 
01490   connection = data;
01491 
01492   _dbus_verbose ("start\n");
01493   
01494   CONNECTION_LOCK (connection);
01495 
01496   if (!_dbus_connection_acquire_io_path (connection, 1))
01497     {
01498       /* another thread is handling the message */
01499       CONNECTION_UNLOCK (connection);
01500       return TRUE;
01501     }
01502 
01503   HAVE_LOCK_CHECK (connection);
01504   retval = _dbus_transport_handle_watch (connection->transport,
01505                                          watch, condition);
01506 
01507   _dbus_connection_release_io_path (connection);
01508 
01509   HAVE_LOCK_CHECK (connection);
01510 
01511   _dbus_verbose ("middle\n");
01512   
01513   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01514 
01515   /* this calls out to user code */
01516   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01517 
01518   _dbus_verbose ("end\n");
01519   
01520   return retval;
01521 }
01522 
01523 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01524 static DBusHashTable *shared_connections = NULL;
01525 static DBusList *shared_connections_no_guid = NULL;
01526 
01527 static void
01528 close_connection_on_shutdown (DBusConnection *connection)
01529 {
01530   DBusMessage *message;
01531 
01532   dbus_connection_ref (connection);
01533   _dbus_connection_close_possibly_shared (connection);
01534 
01535   /* Churn through to the Disconnected message */
01536   while ((message = dbus_connection_pop_message (connection)))
01537     {
01538       dbus_message_unref (message);
01539     }
01540   dbus_connection_unref (connection);
01541 }
01542 
01543 static void
01544 shared_connections_shutdown (void *data)
01545 {
01546   int n_entries;
01547   
01548   _DBUS_LOCK (shared_connections);
01549   
01550   /* This is a little bit unpleasant... better ideas? */
01551   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01552     {
01553       DBusConnection *connection;
01554       DBusHashIter iter;
01555       
01556       _dbus_hash_iter_init (shared_connections, &iter);
01557       _dbus_hash_iter_next (&iter);
01558        
01559       connection = _dbus_hash_iter_get_value (&iter);
01560 
01561       _DBUS_UNLOCK (shared_connections);
01562       close_connection_on_shutdown (connection);
01563       _DBUS_LOCK (shared_connections);
01564 
01565       /* The connection should now be dead and not in our hash ... */
01566       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01567     }
01568 
01569   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01570   
01571   _dbus_hash_table_unref (shared_connections);
01572   shared_connections = NULL;
01573 
01574   if (shared_connections_no_guid != NULL)
01575     {
01576       DBusConnection *connection;
01577       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01578       while (connection != NULL)
01579         {
01580           _DBUS_UNLOCK (shared_connections);
01581           close_connection_on_shutdown (connection);
01582           _DBUS_LOCK (shared_connections);
01583           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01584         }
01585     }
01586 
01587   shared_connections_no_guid = NULL;
01588   
01589   _DBUS_UNLOCK (shared_connections);
01590 }
01591 
01592 static dbus_bool_t
01593 connection_lookup_shared (DBusAddressEntry  *entry,
01594                           DBusConnection   **result)
01595 {
01596   _dbus_verbose ("checking for existing connection\n");
01597   
01598   *result = NULL;
01599   
01600   _DBUS_LOCK (shared_connections);
01601 
01602   if (shared_connections == NULL)
01603     {
01604       _dbus_verbose ("creating shared_connections hash table\n");
01605       
01606       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01607                                                  dbus_free,
01608                                                  NULL);
01609       if (shared_connections == NULL)
01610         {
01611           _DBUS_UNLOCK (shared_connections);
01612           return FALSE;
01613         }
01614 
01615       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01616         {
01617           _dbus_hash_table_unref (shared_connections);
01618           shared_connections = NULL;
01619           _DBUS_UNLOCK (shared_connections);
01620           return FALSE;
01621         }
01622 
01623       _dbus_verbose ("  successfully created shared_connections\n");
01624       
01625       _DBUS_UNLOCK (shared_connections);
01626       return TRUE; /* no point looking up in the hash we just made */
01627     }
01628   else
01629     {
01630       const char *guid;
01631 
01632       guid = dbus_address_entry_get_value (entry, "guid");
01633       
01634       if (guid != NULL)
01635         {
01636           DBusConnection *connection;
01637           
01638           connection = _dbus_hash_table_lookup_string (shared_connections,
01639                                                        guid);
01640 
01641           if (connection)
01642             {
01643               /* The DBusConnection can't be finalized without taking
01644                * the shared_connections lock to remove it from the
01645                * hash.  So it's safe to ref the connection here.
01646                * However, it may be disconnected if the Disconnected
01647                * message hasn't been processed yet, in which case we
01648                * want to pretend it isn't in the hash and avoid
01649                * returning it.
01650                *
01651                * The idea is to avoid ever returning a disconnected connection
01652                * from dbus_connection_open(). We could just synchronously
01653                * drop our shared ref to the connection on connection disconnect,
01654                * and then assert here that the connection is connected, but
01655                * that causes reentrancy headaches.
01656                */
01657               CONNECTION_LOCK (connection);
01658               if (_dbus_connection_get_is_connected_unlocked (connection))
01659                 {
01660                   _dbus_connection_ref_unlocked (connection);
01661                   *result = connection;
01662                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01663                                  guid);
01664                 }
01665               else
01666                 {
01667                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01668                                  guid);
01669                 }
01670               CONNECTION_UNLOCK (connection);
01671             }
01672         }
01673       
01674       _DBUS_UNLOCK (shared_connections);
01675       return TRUE;
01676     }
01677 }
01678 
01679 static dbus_bool_t
01680 connection_record_shared_unlocked (DBusConnection *connection,
01681                                    const char     *guid)
01682 {
01683   char *guid_key;
01684   char *guid_in_connection;
01685 
01686   HAVE_LOCK_CHECK (connection);
01687   _dbus_assert (connection->server_guid == NULL);
01688   _dbus_assert (connection->shareable);
01689 
01690   /* get a hard ref on this connection, even if
01691    * we won't in fact store it in the hash, we still
01692    * need to hold a ref on it until it's disconnected.
01693    */
01694   _dbus_connection_ref_unlocked (connection);
01695 
01696   if (guid == NULL)
01697     {
01698       _DBUS_LOCK (shared_connections);
01699 
01700       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01701         {
01702           _DBUS_UNLOCK (shared_connections);
01703           return FALSE;
01704         }
01705 
01706       _DBUS_UNLOCK (shared_connections);
01707       return TRUE; /* don't store in the hash */
01708     }
01709   
01710   /* A separate copy of the key is required in the hash table, because
01711    * we don't have a lock on the connection when we are doing a hash
01712    * lookup.
01713    */
01714   
01715   guid_key = _dbus_strdup (guid);
01716   if (guid_key == NULL)
01717     return FALSE;
01718 
01719   guid_in_connection = _dbus_strdup (guid);
01720   if (guid_in_connection == NULL)
01721     {
01722       dbus_free (guid_key);
01723       return FALSE;
01724     }
01725   
01726   _DBUS_LOCK (shared_connections);
01727   _dbus_assert (shared_connections != NULL);
01728   
01729   if (!_dbus_hash_table_insert_string (shared_connections,
01730                                        guid_key, connection))
01731     {
01732       dbus_free (guid_key);
01733       dbus_free (guid_in_connection);
01734       _DBUS_UNLOCK (shared_connections);
01735       return FALSE;
01736     }
01737 
01738   connection->server_guid = guid_in_connection;
01739 
01740   _dbus_verbose ("stored connection to %s to be shared\n",
01741                  connection->server_guid);
01742   
01743   _DBUS_UNLOCK (shared_connections);
01744 
01745   _dbus_assert (connection->server_guid != NULL);
01746   
01747   return TRUE;
01748 }
01749 
01750 static void
01751 connection_forget_shared_unlocked (DBusConnection *connection)
01752 {
01753   HAVE_LOCK_CHECK (connection);
01754 
01755   if (!connection->shareable)
01756     return;
01757   
01758   _DBUS_LOCK (shared_connections);
01759       
01760   if (connection->server_guid != NULL)
01761     {
01762       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01763                      connection->server_guid);
01764       
01765       if (!_dbus_hash_table_remove_string (shared_connections,
01766                                            connection->server_guid))
01767         _dbus_assert_not_reached ("connection was not in the shared table");
01768       
01769       dbus_free (connection->server_guid);
01770       connection->server_guid = NULL;
01771     }
01772   else
01773     {
01774       _dbus_list_remove (&shared_connections_no_guid, connection);
01775     }
01776 
01777   _DBUS_UNLOCK (shared_connections);
01778   
01779   /* remove our reference held on all shareable connections */
01780   _dbus_connection_unref_unlocked (connection);
01781 }
01782 
01783 static DBusConnection*
01784 connection_try_from_address_entry (DBusAddressEntry *entry,
01785                                    DBusError        *error)
01786 {
01787   DBusTransport *transport;
01788   DBusConnection *connection;
01789 
01790   transport = _dbus_transport_open (entry, error);
01791 
01792   if (transport == NULL)
01793     {
01794       _DBUS_ASSERT_ERROR_IS_SET (error);
01795       return NULL;
01796     }
01797 
01798   connection = _dbus_connection_new_for_transport (transport);
01799 
01800   _dbus_transport_unref (transport);
01801   
01802   if (connection == NULL)
01803     {
01804       _DBUS_SET_OOM (error);
01805       return NULL;
01806     }
01807 
01808 #ifndef DBUS_DISABLE_CHECKS
01809   _dbus_assert (!connection->have_connection_lock);
01810 #endif
01811   return connection;
01812 }
01813 
01814 /*
01815  * If the shared parameter is true, then any existing connection will
01816  * be used (and if a new connection is created, it will be available
01817  * for use by others). If the shared parameter is false, a new
01818  * connection will always be created, and the new connection will
01819  * never be returned to other callers.
01820  *
01821  * @param address the address
01822  * @param shared whether the connection is shared or private
01823  * @param error error return
01824  * @returns the connection or #NULL on error
01825  */
01826 static DBusConnection*
01827 _dbus_connection_open_internal (const char     *address,
01828                                 dbus_bool_t     shared,
01829                                 DBusError      *error)
01830 {
01831   DBusConnection *connection;
01832   DBusAddressEntry **entries;
01833   DBusError tmp_error = DBUS_ERROR_INIT;
01834   DBusError first_error = DBUS_ERROR_INIT;
01835   int len, i;
01836 
01837   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01838 
01839   _dbus_verbose ("opening %s connection to: %s\n",
01840                  shared ? "shared" : "private", address);
01841   
01842   if (!dbus_parse_address (address, &entries, &len, error))
01843     return NULL;
01844 
01845   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01846   
01847   connection = NULL;
01848 
01849   for (i = 0; i < len; i++)
01850     {
01851       if (shared)
01852         {
01853           if (!connection_lookup_shared (entries[i], &connection))
01854             _DBUS_SET_OOM (&tmp_error);
01855         }
01856 
01857       if (connection == NULL)
01858         {
01859           connection = connection_try_from_address_entry (entries[i],
01860                                                           &tmp_error);
01861 
01862           if (connection != NULL && shared)
01863             {
01864               const char *guid;
01865                   
01866               connection->shareable = TRUE;
01867                   
01868               /* guid may be NULL */
01869               guid = dbus_address_entry_get_value (entries[i], "guid");
01870                   
01871               CONNECTION_LOCK (connection);
01872           
01873               if (!connection_record_shared_unlocked (connection, guid))
01874                 {
01875                   _DBUS_SET_OOM (&tmp_error);
01876                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01877                   dbus_connection_unref (connection);
01878                   connection = NULL;
01879                 }
01880               else
01881                 CONNECTION_UNLOCK (connection);
01882             }
01883         }
01884       
01885       if (connection)
01886         break;
01887 
01888       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01889       
01890       if (i == 0)
01891         dbus_move_error (&tmp_error, &first_error);
01892       else
01893         dbus_error_free (&tmp_error);
01894     }
01895   
01896   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01897   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01898   
01899   if (connection == NULL)
01900     {
01901       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01902       dbus_move_error (&first_error, error);
01903     }
01904   else
01905     dbus_error_free (&first_error);
01906   
01907   dbus_address_entries_free (entries);
01908   return connection;
01909 }
01910 
01919 void
01920 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01921 {
01922   _dbus_assert (connection != NULL);
01923   _dbus_assert (connection->generation == _dbus_current_generation);
01924 
01925   CONNECTION_LOCK (connection);
01926   _dbus_connection_close_possibly_shared_and_unlock (connection);
01927 }
01928 
01929 static DBusPreallocatedSend*
01930 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01931 {
01932   DBusPreallocatedSend *preallocated;
01933 
01934   HAVE_LOCK_CHECK (connection);
01935   
01936   _dbus_assert (connection != NULL);
01937   
01938   preallocated = dbus_new (DBusPreallocatedSend, 1);
01939   if (preallocated == NULL)
01940     return NULL;
01941 
01942   preallocated->queue_link = _dbus_list_alloc_link (NULL);
01943   if (preallocated->queue_link == NULL)
01944     goto failed_0;
01945 
01946   preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01947   if (preallocated->counter_link == NULL)
01948     goto failed_1;
01949 
01950   _dbus_counter_ref (preallocated->counter_link->data);
01951 
01952   preallocated->connection = connection;
01953   
01954   return preallocated;
01955   
01956  failed_1:
01957   _dbus_list_free_link (preallocated->queue_link);
01958  failed_0:
01959   dbus_free (preallocated);
01960   
01961   return NULL;
01962 }
01963 
01964 /* Called with lock held, does not update dispatch status */
01965 static void
01966 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01967                                                        DBusPreallocatedSend *preallocated,
01968                                                        DBusMessage          *message,
01969                                                        dbus_uint32_t        *client_serial)
01970 {
01971   dbus_uint32_t serial;
01972 
01973   preallocated->queue_link->data = message;
01974   _dbus_list_prepend_link (&connection->outgoing_messages,
01975                            preallocated->queue_link);
01976 
01977   /* It's OK that we'll never call the notify function, because for the
01978    * outgoing limit, there isn't one */
01979   _dbus_message_add_counter_link (message,
01980                                   preallocated->counter_link);
01981 
01982   dbus_free (preallocated);
01983   preallocated = NULL;
01984   
01985   dbus_message_ref (message);
01986   
01987   connection->n_outgoing += 1;
01988 
01989   _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01990                  message,
01991                  dbus_message_type_to_string (dbus_message_get_type (message)),
01992                  dbus_message_get_path (message) ?
01993                  dbus_message_get_path (message) :
01994                  "no path",
01995                  dbus_message_get_interface (message) ?
01996                  dbus_message_get_interface (message) :
01997                  "no interface",
01998                  dbus_message_get_member (message) ?
01999                  dbus_message_get_member (message) :
02000                  "no member",
02001                  dbus_message_get_signature (message),
02002                  dbus_message_get_destination (message) ?
02003                  dbus_message_get_destination (message) :
02004                  "null",
02005                  connection,
02006                  connection->n_outgoing);
02007 
02008   if (dbus_message_get_serial (message) == 0)
02009     {
02010       serial = _dbus_connection_get_next_client_serial (connection);
02011       dbus_message_set_serial (message, serial);
02012       if (client_serial)
02013         *client_serial = serial;
02014     }
02015   else
02016     {
02017       if (client_serial)
02018         *client_serial = dbus_message_get_serial (message);
02019     }
02020 
02021   _dbus_verbose ("Message %p serial is %u\n",
02022                  message, dbus_message_get_serial (message));
02023   
02024   dbus_message_lock (message);
02025 
02026   /* Now we need to run an iteration to hopefully just write the messages
02027    * out immediately, and otherwise get them queued up
02028    */
02029   _dbus_connection_do_iteration_unlocked (connection,
02030                                           NULL,
02031                                           DBUS_ITERATION_DO_WRITING,
02032                                           -1);
02033 
02034   /* If stuff is still queued up, be sure we wake up the main loop */
02035   if (connection->n_outgoing > 0)
02036     _dbus_connection_wakeup_mainloop (connection);
02037 }
02038 
02039 static void
02040 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02041                                                DBusPreallocatedSend *preallocated,
02042                                                DBusMessage          *message,
02043                                                dbus_uint32_t        *client_serial)
02044 {
02045   DBusDispatchStatus status;
02046 
02047   HAVE_LOCK_CHECK (connection);
02048   
02049   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02050                                                          preallocated,
02051                                                          message, client_serial);
02052 
02053   _dbus_verbose ("middle\n");
02054   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02055 
02056   /* this calls out to user code */
02057   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02058 }
02059 
02069 dbus_bool_t
02070 _dbus_connection_send_and_unlock (DBusConnection *connection,
02071                                   DBusMessage    *message,
02072                                   dbus_uint32_t  *client_serial)
02073 {
02074   DBusPreallocatedSend *preallocated;
02075 
02076   _dbus_assert (connection != NULL);
02077   _dbus_assert (message != NULL);
02078   
02079   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02080   if (preallocated == NULL)
02081     {
02082       CONNECTION_UNLOCK (connection);
02083       return FALSE;
02084     }
02085 
02086   _dbus_connection_send_preallocated_and_unlock (connection,
02087                                                  preallocated,
02088                                                  message,
02089                                                  client_serial);
02090   return TRUE;
02091 }
02092 
02117 void
02118 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02119 {
02120   dbus_int32_t refcount;
02121 
02122   CONNECTION_LOCK (connection);
02123 
02124   refcount = _dbus_atomic_get (&connection->refcount);
02125   /* The caller should have at least one ref */
02126   _dbus_assert (refcount >= 1);
02127 
02128   if (refcount == 1)
02129     _dbus_connection_close_possibly_shared_and_unlock (connection);
02130   else
02131     CONNECTION_UNLOCK (connection);
02132 }
02133 
02134 
02144 static void
02145 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02146 {
02147   if (timeout_milliseconds == -1)
02148     _dbus_sleep_milliseconds (1000);
02149   else if (timeout_milliseconds < 100)
02150     ; /* just busy loop */
02151   else if (timeout_milliseconds <= 1000)
02152     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02153   else
02154     _dbus_sleep_milliseconds (1000);
02155 }
02156 
02157 static DBusMessage *
02158 generate_local_error_message (dbus_uint32_t serial, 
02159                               char *error_name, 
02160                               char *error_msg)
02161 {
02162   DBusMessage *message;
02163   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02164   if (!message)
02165     goto out;
02166 
02167   if (!dbus_message_set_error_name (message, error_name))
02168     {
02169       dbus_message_unref (message);
02170       message = NULL;
02171       goto out; 
02172     }
02173 
02174   dbus_message_set_no_reply (message, TRUE); 
02175 
02176   if (!dbus_message_set_reply_serial (message,
02177                                       serial))
02178     {
02179       dbus_message_unref (message);
02180       message = NULL;
02181       goto out;
02182     }
02183 
02184   if (error_msg != NULL)
02185     {
02186       DBusMessageIter iter;
02187 
02188       dbus_message_iter_init_append (message, &iter);
02189       if (!dbus_message_iter_append_basic (&iter,
02190                                            DBUS_TYPE_STRING,
02191                                            &error_msg))
02192         {
02193           dbus_message_unref (message);
02194           message = NULL;
02195           goto out;
02196         }
02197     }
02198 
02199  out:
02200   return message;
02201 }
02202 
02203 /*
02204  * Peek the incoming queue to see if we got reply for a specific serial
02205  */
02206 static dbus_bool_t
02207 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02208                                           dbus_uint32_t   client_serial)
02209 {
02210   DBusList *link;
02211   HAVE_LOCK_CHECK (connection);
02212 
02213   link = _dbus_list_get_first_link (&connection->incoming_messages);
02214 
02215   while (link != NULL)
02216     {
02217       DBusMessage *reply = link->data;
02218 
02219       if (dbus_message_get_reply_serial (reply) == client_serial)
02220         {
02221           _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02222           return TRUE;
02223         }
02224       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02225     }
02226 
02227   return FALSE;
02228 }
02229 
02230 /* This is slightly strange since we can pop a message here without
02231  * the dispatch lock.
02232  */
02233 static DBusMessage*
02234 check_for_reply_unlocked (DBusConnection *connection,
02235                           dbus_uint32_t   client_serial)
02236 {
02237   DBusList *link;
02238 
02239   HAVE_LOCK_CHECK (connection);
02240   
02241   link = _dbus_list_get_first_link (&connection->incoming_messages);
02242 
02243   while (link != NULL)
02244     {
02245       DBusMessage *reply = link->data;
02246 
02247       if (dbus_message_get_reply_serial (reply) == client_serial)
02248         {
02249           _dbus_list_remove_link (&connection->incoming_messages, link);
02250           connection->n_incoming  -= 1;
02251           return reply;
02252         }
02253       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02254     }
02255 
02256   return NULL;
02257 }
02258 
02259 static void
02260 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02261 {
02262    /* We can't iterate over the hash in the normal way since we'll be
02263     * dropping the lock for each item. So we restart the
02264     * iter each time as we drain the hash table.
02265     */
02266    
02267    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02268     {
02269       DBusPendingCall *pending;
02270       DBusHashIter iter;
02271       
02272       _dbus_hash_iter_init (connection->pending_replies, &iter);
02273       _dbus_hash_iter_next (&iter);
02274        
02275       pending = _dbus_hash_iter_get_value (&iter);
02276       _dbus_pending_call_ref_unlocked (pending);
02277        
02278       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02279                                                        connection);
02280 
02281       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02282           _dbus_connection_remove_timeout_unlocked (connection,
02283                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02284       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02285       _dbus_hash_iter_remove_entry (&iter);
02286 
02287       _dbus_pending_call_unref_and_unlock (pending);
02288       CONNECTION_LOCK (connection);
02289     }
02290   HAVE_LOCK_CHECK (connection);
02291 }
02292 
02293 static void
02294 complete_pending_call_and_unlock (DBusConnection  *connection,
02295                                   DBusPendingCall *pending,
02296                                   DBusMessage     *message)
02297 {
02298   _dbus_pending_call_set_reply_unlocked (pending, message);
02299   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02300   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02301  
02302   /* Must be called unlocked since it invokes app callback */
02303   _dbus_pending_call_complete (pending);
02304   dbus_pending_call_unref (pending);
02305 }
02306 
02307 static dbus_bool_t
02308 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02309                                               DBusPendingCall *pending)
02310 {
02311   DBusMessage *reply;
02312   DBusDispatchStatus status;
02313 
02314   reply = check_for_reply_unlocked (connection, 
02315                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02316   if (reply != NULL)
02317     {
02318       _dbus_verbose ("checked for reply\n");
02319 
02320       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02321 
02322       complete_pending_call_and_unlock (connection, pending, reply);
02323       dbus_message_unref (reply);
02324 
02325       CONNECTION_LOCK (connection);
02326       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02327       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02328       dbus_pending_call_unref (pending);
02329 
02330       return TRUE;
02331     }
02332 
02333   return FALSE;
02334 }
02335 
02350 void
02351 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02352 {
02353   long start_tv_sec, start_tv_usec;
02354   long tv_sec, tv_usec;
02355   DBusDispatchStatus status;
02356   DBusConnection *connection;
02357   dbus_uint32_t client_serial;
02358   DBusTimeout *timeout;
02359   int timeout_milliseconds, elapsed_milliseconds;
02360 
02361   _dbus_assert (pending != NULL);
02362 
02363   if (dbus_pending_call_get_completed (pending))
02364     return;
02365 
02366   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02367 
02368   connection = _dbus_pending_call_get_connection_and_lock (pending);
02369   
02370   /* Flush message queue - note, can affect dispatch status */
02371   _dbus_connection_flush_unlocked (connection);
02372 
02373   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02374 
02375   /* note that timeout_milliseconds is limited to a smallish value
02376    * in _dbus_pending_call_new() so overflows aren't possible
02377    * below
02378    */
02379   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02380   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02381   if (timeout)
02382     {
02383       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02384 
02385       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02386                      timeout_milliseconds,
02387                      client_serial,
02388                      start_tv_sec, start_tv_usec);
02389     }
02390   else
02391     {
02392       timeout_milliseconds = -1;
02393 
02394       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02395     }
02396 
02397   /* check to see if we already got the data off the socket */
02398   /* from another blocked pending call */
02399   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02400     return;
02401 
02402   /* Now we wait... */
02403   /* always block at least once as we know we don't have the reply yet */
02404   _dbus_connection_do_iteration_unlocked (connection,
02405                                           pending,
02406                                           DBUS_ITERATION_DO_READING |
02407                                           DBUS_ITERATION_BLOCK,
02408                                           timeout_milliseconds);
02409 
02410  recheck_status:
02411 
02412   _dbus_verbose ("top of recheck\n");
02413   
02414   HAVE_LOCK_CHECK (connection);
02415   
02416   /* queue messages and get status */
02417 
02418   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02419 
02420   /* the get_completed() is in case a dispatch() while we were blocking
02421    * got the reply instead of us.
02422    */
02423   if (_dbus_pending_call_get_completed_unlocked (pending))
02424     {
02425       _dbus_verbose ("Pending call completed by dispatch\n");
02426       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02427       dbus_pending_call_unref (pending);
02428       return;
02429     }
02430   
02431   if (status == DBUS_DISPATCH_DATA_REMAINS)
02432     {
02433       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02434         return;
02435     }
02436   
02437   _dbus_get_current_time (&tv_sec, &tv_usec);
02438   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02439           (tv_usec - start_tv_usec) / 1000;
02440   
02441   if (!_dbus_connection_get_is_connected_unlocked (connection))
02442     {
02443       DBusMessage *error_msg;
02444 
02445       error_msg = generate_local_error_message (client_serial,
02446                                                 DBUS_ERROR_DISCONNECTED, 
02447                                                 "Connection was disconnected before a reply was received"); 
02448 
02449       /* on OOM error_msg is set to NULL */
02450       complete_pending_call_and_unlock (connection, pending, error_msg);
02451       dbus_pending_call_unref (pending);
02452       return;
02453     }
02454   else if (connection->disconnect_message_link == NULL)
02455     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02456   else if (timeout == NULL)
02457     {
02458        if (status == DBUS_DISPATCH_NEED_MEMORY)
02459         {
02460           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02461            * we may already have a reply in the buffer and just can't process
02462            * it.
02463            */
02464           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02465 
02466           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02467         }
02468       else
02469         {          
02470           /* block again, we don't have the reply buffered yet. */
02471           _dbus_connection_do_iteration_unlocked (connection,
02472                                                   pending,
02473                                                   DBUS_ITERATION_DO_READING |
02474                                                   DBUS_ITERATION_BLOCK,
02475                                                   timeout_milliseconds - elapsed_milliseconds);
02476         }
02477 
02478       goto recheck_status;
02479     }
02480   else if (tv_sec < start_tv_sec)
02481     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02482   else if (elapsed_milliseconds < timeout_milliseconds)
02483     {
02484       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02485       
02486       if (status == DBUS_DISPATCH_NEED_MEMORY)
02487         {
02488           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02489            * we may already have a reply in the buffer and just can't process
02490            * it.
02491            */
02492           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02493 
02494           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02495         }
02496       else
02497         {          
02498           /* block again, we don't have the reply buffered yet. */
02499           _dbus_connection_do_iteration_unlocked (connection,
02500                                                   NULL,
02501                                                   DBUS_ITERATION_DO_READING |
02502                                                   DBUS_ITERATION_BLOCK,
02503                                                   timeout_milliseconds - elapsed_milliseconds);
02504         }
02505 
02506       goto recheck_status;
02507     }
02508 
02509   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02510                  elapsed_milliseconds);
02511 
02512   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02513   
02514   /* unlock and call user code */
02515   complete_pending_call_and_unlock (connection, pending, NULL);
02516 
02517   /* update user code on dispatch status */
02518   CONNECTION_LOCK (connection);
02519   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02520   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02521   dbus_pending_call_unref (pending);
02522 }
02523 
02560 DBusConnection*
02561 dbus_connection_open (const char     *address,
02562                       DBusError      *error)
02563 {
02564   DBusConnection *connection;
02565 
02566   _dbus_return_val_if_fail (address != NULL, NULL);
02567   _dbus_return_val_if_error_is_set (error, NULL);
02568 
02569   connection = _dbus_connection_open_internal (address,
02570                                                TRUE,
02571                                                error);
02572 
02573   return connection;
02574 }
02575 
02603 DBusConnection*
02604 dbus_connection_open_private (const char     *address,
02605                               DBusError      *error)
02606 {
02607   DBusConnection *connection;
02608 
02609   _dbus_return_val_if_fail (address != NULL, NULL);
02610   _dbus_return_val_if_error_is_set (error, NULL);
02611 
02612   connection = _dbus_connection_open_internal (address,
02613                                                FALSE,
02614                                                error);
02615 
02616   return connection;
02617 }
02618 
02625 DBusConnection *
02626 dbus_connection_ref (DBusConnection *connection)
02627 {
02628   _dbus_return_val_if_fail (connection != NULL, NULL);
02629   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02630 
02631   _dbus_atomic_inc (&connection->refcount);
02632 
02633   return connection;
02634 }
02635 
02636 static void
02637 free_outgoing_message (void *element,
02638                        void *data)
02639 {
02640   DBusMessage *message = element;
02641   DBusConnection *connection = data;
02642 
02643   _dbus_message_remove_counter (message,
02644                                 connection->outgoing_counter,
02645                                 NULL);
02646   dbus_message_unref (message);
02647 }
02648 
02649 /* This is run without the mutex held, but after the last reference
02650  * to the connection has been dropped we should have no thread-related
02651  * problems
02652  */
02653 static void
02654 _dbus_connection_last_unref (DBusConnection *connection)
02655 {
02656   DBusList *link;
02657 
02658   _dbus_verbose ("Finalizing connection %p\n", connection);
02659 
02660   _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02661 
02662   /* You have to disconnect the connection before unref:ing it. Otherwise
02663    * you won't get the disconnected message.
02664    */
02665   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02666   _dbus_assert (connection->server_guid == NULL);
02667   
02668   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02669   _dbus_object_tree_free_all_unlocked (connection->objects);
02670   
02671   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02672   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02673   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02674   
02675   _dbus_watch_list_free (connection->watches);
02676   connection->watches = NULL;
02677   
02678   _dbus_timeout_list_free (connection->timeouts);
02679   connection->timeouts = NULL;
02680 
02681   _dbus_data_slot_list_free (&connection->slot_list);
02682   
02683   link = _dbus_list_get_first_link (&connection->filter_list);
02684   while (link != NULL)
02685     {
02686       DBusMessageFilter *filter = link->data;
02687       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02688 
02689       filter->function = NULL;
02690       _dbus_message_filter_unref (filter); /* calls app callback */
02691       link->data = NULL;
02692       
02693       link = next;
02694     }
02695   _dbus_list_clear (&connection->filter_list);
02696   
02697   /* ---- Done with stuff that invokes application callbacks */
02698 
02699   _dbus_object_tree_unref (connection->objects);  
02700 
02701   _dbus_hash_table_unref (connection->pending_replies);
02702   connection->pending_replies = NULL;
02703   
02704   _dbus_list_clear (&connection->filter_list);
02705   
02706   _dbus_list_foreach (&connection->outgoing_messages,
02707                       free_outgoing_message,
02708                       connection);
02709   _dbus_list_clear (&connection->outgoing_messages);
02710   
02711   _dbus_list_foreach (&connection->incoming_messages,
02712                       (DBusForeachFunction) dbus_message_unref,
02713                       NULL);
02714   _dbus_list_clear (&connection->incoming_messages);
02715 
02716   _dbus_counter_unref (connection->outgoing_counter);
02717 
02718   _dbus_transport_unref (connection->transport);
02719 
02720   if (connection->disconnect_message_link)
02721     {
02722       DBusMessage *message = connection->disconnect_message_link->data;
02723       dbus_message_unref (message);
02724       _dbus_list_free_link (connection->disconnect_message_link);
02725     }
02726 
02727   _dbus_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   _dbus_connection_ref_unlocked (connection);
03279 
03280   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03281                                                    connection);
03282   _dbus_connection_remove_timeout_unlocked (connection,
03283                                             _dbus_pending_call_get_timeout_unlocked (pending));
03284   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03285 
03286   _dbus_verbose ("middle\n");
03287   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03288 
03289   /* Unlocks, and calls out to user code */
03290   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03291   dbus_connection_unref (connection);
03292   
03293   return TRUE;
03294 }
03295 
03335 dbus_bool_t
03336 dbus_connection_send_with_reply (DBusConnection     *connection,
03337                                  DBusMessage        *message,
03338                                  DBusPendingCall   **pending_return,
03339                                  int                 timeout_milliseconds)
03340 {
03341   DBusPendingCall *pending;
03342   dbus_int32_t serial = -1;
03343   DBusDispatchStatus status;
03344 
03345   _dbus_return_val_if_fail (connection != NULL, FALSE);
03346   _dbus_return_val_if_fail (message != NULL, FALSE);
03347   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03348 
03349   if (pending_return)
03350     *pending_return = NULL;
03351 
03352   CONNECTION_LOCK (connection);
03353 
03354 #ifdef HAVE_UNIX_FD_PASSING
03355 
03356   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03357       message->n_unix_fds > 0)
03358     {
03359       /* Refuse to send fds on a connection that cannot handle
03360          them. Unfortunately we cannot return a proper error here, so
03361          the best we can do is return TRUE but leave *pending_return
03362          as NULL. */
03363       CONNECTION_UNLOCK (connection);
03364       return TRUE;
03365     }
03366 
03367 #endif
03368 
03369    if (!_dbus_connection_get_is_connected_unlocked (connection))
03370     {
03371       CONNECTION_UNLOCK (connection);
03372 
03373       return TRUE;
03374     }
03375 
03376   pending = _dbus_pending_call_new_unlocked (connection,
03377                                              timeout_milliseconds,
03378                                              reply_handler_timeout);
03379 
03380   if (pending == NULL)
03381     {
03382       CONNECTION_UNLOCK (connection);
03383       return FALSE;
03384     }
03385 
03386   /* Assign a serial to the message */
03387   serial = dbus_message_get_serial (message);
03388   if (serial == 0)
03389     {
03390       serial = _dbus_connection_get_next_client_serial (connection);
03391       dbus_message_set_serial (message, serial);
03392     }
03393 
03394   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03395     goto error;
03396     
03397   /* Insert the serial in the pending replies hash;
03398    * hash takes a refcount on DBusPendingCall.
03399    * Also, add the timeout.
03400    */
03401   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03402                                                       pending))
03403     goto error;
03404  
03405   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03406     {
03407       _dbus_connection_detach_pending_call_and_unlock (connection,
03408                                                        pending);
03409       goto error_unlocked;
03410     }
03411 
03412   if (pending_return)
03413     *pending_return = pending; /* hand off refcount */
03414   else
03415     {
03416       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03417       /* we still have a ref to the pending call in this case, we unref
03418        * after unlocking, below
03419        */
03420     }
03421 
03422   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03423 
03424   /* this calls out to user code */
03425   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03426 
03427   if (pending_return == NULL)
03428     dbus_pending_call_unref (pending);
03429   
03430   return TRUE;
03431 
03432  error:
03433   CONNECTION_UNLOCK (connection);
03434  error_unlocked:
03435   dbus_pending_call_unref (pending);
03436   return FALSE;
03437 }
03438 
03469 DBusMessage*
03470 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03471                                            DBusMessage        *message,
03472                                            int                 timeout_milliseconds,
03473                                            DBusError          *error)
03474 {
03475   DBusMessage *reply;
03476   DBusPendingCall *pending;
03477 
03478   _dbus_return_val_if_fail (connection != NULL, NULL);
03479   _dbus_return_val_if_fail (message != NULL, NULL);
03480   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03481   _dbus_return_val_if_error_is_set (error, NULL);
03482 
03483 #ifdef HAVE_UNIX_FD_PASSING
03484 
03485   CONNECTION_LOCK (connection);
03486   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03487       message->n_unix_fds > 0)
03488     {
03489       CONNECTION_UNLOCK (connection);
03490       dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03491       return NULL;
03492     }
03493   CONNECTION_UNLOCK (connection);
03494 
03495 #endif
03496 
03497   if (!dbus_connection_send_with_reply (connection, message,
03498                                         &pending, timeout_milliseconds))
03499     {
03500       _DBUS_SET_OOM (error);
03501       return NULL;
03502     }
03503 
03504   if (pending == NULL)
03505     {
03506       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03507       return NULL;
03508     }
03509   
03510   dbus_pending_call_block (pending);
03511 
03512   reply = dbus_pending_call_steal_reply (pending);
03513   dbus_pending_call_unref (pending);
03514 
03515   /* call_complete_and_unlock() called from pending_call_block() should
03516    * always fill this in.
03517    */
03518   _dbus_assert (reply != NULL);
03519   
03520    if (dbus_set_error_from_message (error, reply))
03521     {
03522       dbus_message_unref (reply);
03523       return NULL;
03524     }
03525   else
03526     return reply;
03527 }
03528 
03537 static DBusDispatchStatus
03538 _dbus_connection_flush_unlocked (DBusConnection *connection)
03539 {
03540   /* We have to specify DBUS_ITERATION_DO_READING here because
03541    * otherwise we could have two apps deadlock if they are both doing
03542    * a flush(), and the kernel buffers fill up. This could change the
03543    * dispatch status.
03544    */
03545   DBusDispatchStatus status;
03546 
03547   HAVE_LOCK_CHECK (connection);
03548   
03549   while (connection->n_outgoing > 0 &&
03550          _dbus_connection_get_is_connected_unlocked (connection))
03551     {
03552       _dbus_verbose ("doing iteration in\n");
03553       HAVE_LOCK_CHECK (connection);
03554       _dbus_connection_do_iteration_unlocked (connection,
03555                                               NULL,
03556                                               DBUS_ITERATION_DO_READING |
03557                                               DBUS_ITERATION_DO_WRITING |
03558                                               DBUS_ITERATION_BLOCK,
03559                                               -1);
03560     }
03561 
03562   HAVE_LOCK_CHECK (connection);
03563   _dbus_verbose ("middle\n");
03564   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03565 
03566   HAVE_LOCK_CHECK (connection);
03567   return status;
03568 }
03569 
03575 void
03576 dbus_connection_flush (DBusConnection *connection)
03577 {
03578   /* We have to specify DBUS_ITERATION_DO_READING here because
03579    * otherwise we could have two apps deadlock if they are both doing
03580    * a flush(), and the kernel buffers fill up. This could change the
03581    * dispatch status.
03582    */
03583   DBusDispatchStatus status;
03584 
03585   _dbus_return_if_fail (connection != NULL);
03586   
03587   CONNECTION_LOCK (connection);
03588 
03589   status = _dbus_connection_flush_unlocked (connection);
03590   
03591   HAVE_LOCK_CHECK (connection);
03592   /* Unlocks and calls out to user code */
03593   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03594 
03595   _dbus_verbose ("end\n");
03596 }
03597 
03608 static dbus_bool_t
03609 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03610                                      int             timeout_milliseconds, 
03611                                      dbus_bool_t     dispatch)
03612 {
03613   DBusDispatchStatus dstatus;
03614   dbus_bool_t progress_possible;
03615 
03616   /* Need to grab a ref here in case we're a private connection and
03617    * the user drops the last ref in a handler we call; see bug 
03618    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03619    */
03620   dbus_connection_ref (connection);
03621   dstatus = dbus_connection_get_dispatch_status (connection);
03622 
03623   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03624     {
03625       _dbus_verbose ("doing dispatch\n");
03626       dbus_connection_dispatch (connection);
03627       CONNECTION_LOCK (connection);
03628     }
03629   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03630     {
03631       _dbus_verbose ("pausing for memory\n");
03632       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03633       CONNECTION_LOCK (connection);
03634     }
03635   else
03636     {
03637       CONNECTION_LOCK (connection);
03638       if (_dbus_connection_get_is_connected_unlocked (connection))
03639         {
03640           _dbus_verbose ("doing iteration\n");
03641           _dbus_connection_do_iteration_unlocked (connection,
03642                                                   NULL,
03643                                                   DBUS_ITERATION_DO_READING |
03644                                                   DBUS_ITERATION_DO_WRITING |
03645                                                   DBUS_ITERATION_BLOCK,
03646                                                   timeout_milliseconds);
03647         }
03648     }
03649   
03650   HAVE_LOCK_CHECK (connection);
03651   /* If we can dispatch, we can make progress until the Disconnected message
03652    * has been processed; if we can only read/write, we can make progress
03653    * as long as the transport is open.
03654    */
03655   if (dispatch)
03656     progress_possible = connection->n_incoming != 0 ||
03657       connection->disconnect_message_link != NULL;
03658   else
03659     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03660 
03661   CONNECTION_UNLOCK (connection);
03662 
03663   dbus_connection_unref (connection);
03664 
03665   return progress_possible; /* TRUE if we can make more progress */
03666 }
03667 
03668 
03703 dbus_bool_t
03704 dbus_connection_read_write_dispatch (DBusConnection *connection,
03705                                      int             timeout_milliseconds)
03706 {
03707   _dbus_return_val_if_fail (connection != NULL, FALSE);
03708   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03709    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03710 }
03711 
03735 dbus_bool_t 
03736 dbus_connection_read_write (DBusConnection *connection, 
03737                             int             timeout_milliseconds) 
03738 { 
03739   _dbus_return_val_if_fail (connection != NULL, FALSE);
03740   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03741    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03742 }
03743 
03744 /* We need to call this anytime we pop the head of the queue, and then
03745  * update_dispatch_status_and_unlock needs to be called afterward
03746  * which will "process" the disconnected message and set
03747  * disconnected_message_processed.
03748  */
03749 static void
03750 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03751                                              DBusMessage    *head_of_queue)
03752 {
03753   HAVE_LOCK_CHECK (connection);
03754 
03755   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03756   if (connection->disconnect_message_link == NULL &&
03757       dbus_message_is_signal (head_of_queue,
03758                               DBUS_INTERFACE_LOCAL,
03759                               "Disconnected"))
03760     {
03761       connection->disconnected_message_arrived = TRUE;
03762     }
03763 }
03764 
03784 DBusMessage*
03785 dbus_connection_borrow_message (DBusConnection *connection)
03786 {
03787   DBusDispatchStatus status;
03788   DBusMessage *message;
03789 
03790   _dbus_return_val_if_fail (connection != NULL, NULL);
03791 
03792   _dbus_verbose ("start\n");
03793   
03794   /* this is called for the side effect that it queues
03795    * up any messages from the transport
03796    */
03797   status = dbus_connection_get_dispatch_status (connection);
03798   if (status != DBUS_DISPATCH_DATA_REMAINS)
03799     return NULL;
03800   
03801   CONNECTION_LOCK (connection);
03802 
03803   _dbus_connection_acquire_dispatch (connection);
03804 
03805   /* While a message is outstanding, the dispatch lock is held */
03806   _dbus_assert (connection->message_borrowed == NULL);
03807 
03808   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03809   
03810   message = connection->message_borrowed;
03811 
03812   check_disconnected_message_arrived_unlocked (connection, message);
03813   
03814   /* Note that we KEEP the dispatch lock until the message is returned */
03815   if (message == NULL)
03816     _dbus_connection_release_dispatch (connection);
03817 
03818   CONNECTION_UNLOCK (connection);
03819 
03820   /* We don't update dispatch status until it's returned or stolen */
03821   
03822   return message;
03823 }
03824 
03833 void
03834 dbus_connection_return_message (DBusConnection *connection,
03835                                 DBusMessage    *message)
03836 {
03837   DBusDispatchStatus status;
03838   
03839   _dbus_return_if_fail (connection != NULL);
03840   _dbus_return_if_fail (message != NULL);
03841   _dbus_return_if_fail (message == connection->message_borrowed);
03842   _dbus_return_if_fail (connection->dispatch_acquired);
03843   
03844   CONNECTION_LOCK (connection);
03845   
03846   _dbus_assert (message == connection->message_borrowed);
03847   
03848   connection->message_borrowed = NULL;
03849 
03850   _dbus_connection_release_dispatch (connection); 
03851 
03852   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03853   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03854 }
03855 
03865 void
03866 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03867                                         DBusMessage    *message)
03868 {
03869   DBusMessage *pop_message;
03870   DBusDispatchStatus status;
03871 
03872   _dbus_return_if_fail (connection != NULL);
03873   _dbus_return_if_fail (message != NULL);
03874   _dbus_return_if_fail (message == connection->message_borrowed);
03875   _dbus_return_if_fail (connection->dispatch_acquired);
03876   
03877   CONNECTION_LOCK (connection);
03878  
03879   _dbus_assert (message == connection->message_borrowed);
03880 
03881   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03882   _dbus_assert (message == pop_message);
03883   
03884   connection->n_incoming -= 1;
03885  
03886   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03887                  message, connection->n_incoming);
03888  
03889   connection->message_borrowed = NULL;
03890 
03891   _dbus_connection_release_dispatch (connection);
03892 
03893   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03894   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03895 }
03896 
03897 /* See dbus_connection_pop_message, but requires the caller to own
03898  * the lock before calling. May drop the lock while running.
03899  */
03900 static DBusList*
03901 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03902 {
03903   HAVE_LOCK_CHECK (connection);
03904   
03905   _dbus_assert (connection->message_borrowed == NULL);
03906   
03907   if (connection->n_incoming > 0)
03908     {
03909       DBusList *link;
03910 
03911       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03912       connection->n_incoming -= 1;
03913 
03914       _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03915                      link->data,
03916                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
03917                      dbus_message_get_path (link->data) ?
03918                      dbus_message_get_path (link->data) :
03919                      "no path",
03920                      dbus_message_get_interface (link->data) ?
03921                      dbus_message_get_interface (link->data) :
03922                      "no interface",
03923                      dbus_message_get_member (link->data) ?
03924                      dbus_message_get_member (link->data) :
03925                      "no member",
03926                      dbus_message_get_signature (link->data),
03927                      connection, connection->n_incoming);
03928 
03929       check_disconnected_message_arrived_unlocked (connection, link->data);
03930       
03931       return link;
03932     }
03933   else
03934     return NULL;
03935 }
03936 
03937 /* See dbus_connection_pop_message, but requires the caller to own
03938  * the lock before calling. May drop the lock while running.
03939  */
03940 static DBusMessage*
03941 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03942 {
03943   DBusList *link;
03944 
03945   HAVE_LOCK_CHECK (connection);
03946   
03947   link = _dbus_connection_pop_message_link_unlocked (connection);
03948 
03949   if (link != NULL)
03950     {
03951       DBusMessage *message;
03952       
03953       message = link->data;
03954       
03955       _dbus_list_free_link (link);
03956       
03957       return message;
03958     }
03959   else
03960     return NULL;
03961 }
03962 
03963 static void
03964 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03965                                                 DBusList       *message_link)
03966 {
03967   HAVE_LOCK_CHECK (connection);
03968   
03969   _dbus_assert (message_link != NULL);
03970   /* You can't borrow a message while a link is outstanding */
03971   _dbus_assert (connection->message_borrowed == NULL);
03972   /* We had to have the dispatch lock across the pop/putback */
03973   _dbus_assert (connection->dispatch_acquired);
03974 
03975   _dbus_list_prepend_link (&connection->incoming_messages,
03976                            message_link);
03977   connection->n_incoming += 1;
03978 
03979   _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
03980                  message_link->data,
03981                  dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
03982                  dbus_message_get_interface (message_link->data) ?
03983                  dbus_message_get_interface (message_link->data) :
03984                  "no interface",
03985                  dbus_message_get_member (message_link->data) ?
03986                  dbus_message_get_member (message_link->data) :
03987                  "no member",
03988                  dbus_message_get_signature (message_link->data),
03989                  connection, connection->n_incoming);
03990 }
03991 
04011 DBusMessage*
04012 dbus_connection_pop_message (DBusConnection *connection)
04013 {
04014   DBusMessage *message;
04015   DBusDispatchStatus status;
04016 
04017   _dbus_verbose ("start\n");
04018   
04019   /* this is called for the side effect that it queues
04020    * up any messages from the transport
04021    */
04022   status = dbus_connection_get_dispatch_status (connection);
04023   if (status != DBUS_DISPATCH_DATA_REMAINS)
04024     return NULL;
04025   
04026   CONNECTION_LOCK (connection);
04027   _dbus_connection_acquire_dispatch (connection);
04028   HAVE_LOCK_CHECK (connection);
04029   
04030   message = _dbus_connection_pop_message_unlocked (connection);
04031 
04032   _dbus_verbose ("Returning popped message %p\n", message);    
04033 
04034   _dbus_connection_release_dispatch (connection);
04035 
04036   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04037   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04038   
04039   return message;
04040 }
04041 
04049 static void
04050 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04051 {
04052   HAVE_LOCK_CHECK (connection);
04053 
04054   _dbus_connection_ref_unlocked (connection);
04055   CONNECTION_UNLOCK (connection);
04056   
04057   _dbus_verbose ("locking dispatch_mutex\n");
04058   _dbus_mutex_lock (connection->dispatch_mutex);
04059 
04060   while (connection->dispatch_acquired)
04061     {
04062       _dbus_verbose ("waiting for dispatch to be acquirable\n");
04063       _dbus_condvar_wait (connection->dispatch_cond, 
04064                           connection->dispatch_mutex);
04065     }
04066   
04067   _dbus_assert (!connection->dispatch_acquired);
04068 
04069   connection->dispatch_acquired = TRUE;
04070 
04071   _dbus_verbose ("unlocking dispatch_mutex\n");
04072   _dbus_mutex_unlock (connection->dispatch_mutex);
04073   
04074   CONNECTION_LOCK (connection);
04075   _dbus_connection_unref_unlocked (connection);
04076 }
04077 
04085 static void
04086 _dbus_connection_release_dispatch (DBusConnection *connection)
04087 {
04088   HAVE_LOCK_CHECK (connection);
04089   
04090   _dbus_verbose ("locking dispatch_mutex\n");
04091   _dbus_mutex_lock (connection->dispatch_mutex);
04092   
04093   _dbus_assert (connection->dispatch_acquired);
04094 
04095   connection->dispatch_acquired = FALSE;
04096   _dbus_condvar_wake_one (connection->dispatch_cond);
04097 
04098   _dbus_verbose ("unlocking dispatch_mutex\n");
04099   _dbus_mutex_unlock (connection->dispatch_mutex);
04100 }
04101 
04102 static void
04103 _dbus_connection_failed_pop (DBusConnection *connection,
04104                              DBusList       *message_link)
04105 {
04106   _dbus_list_prepend_link (&connection->incoming_messages,
04107                            message_link);
04108   connection->n_incoming += 1;
04109 }
04110 
04111 /* Note this may be called multiple times since we don't track whether we already did it */
04112 static void
04113 notify_disconnected_unlocked (DBusConnection *connection)
04114 {
04115   HAVE_LOCK_CHECK (connection);
04116 
04117   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04118    * connection from dbus_bus_get(). We make the same guarantee for
04119    * dbus_connection_open() but in a different way since we don't want to
04120    * unref right here; we instead check for connectedness before returning
04121    * the connection from the hash.
04122    */
04123   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04124 
04125   /* Dump the outgoing queue, we aren't going to be able to
04126    * send it now, and we'd like accessors like
04127    * dbus_connection_get_outgoing_size() to be accurate.
04128    */
04129   if (connection->n_outgoing > 0)
04130     {
04131       DBusList *link;
04132       
04133       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04134                      connection->n_outgoing);
04135       
04136       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04137         {
04138           _dbus_connection_message_sent_unlocked (connection, link->data);
04139         }
04140     } 
04141 }
04142 
04143 /* Note this may be called multiple times since we don't track whether we already did it */
04144 static DBusDispatchStatus
04145 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04146 {
04147   HAVE_LOCK_CHECK (connection);
04148   
04149   if (connection->disconnect_message_link != NULL)
04150     {
04151       _dbus_verbose ("Sending disconnect message\n");
04152       
04153       /* If we have pending calls, queue their timeouts - we want the Disconnected
04154        * to be the last message, after these timeouts.
04155        */
04156       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04157       
04158       /* We haven't sent the disconnect message already,
04159        * and all real messages have been queued up.
04160        */
04161       _dbus_connection_queue_synthesized_message_link (connection,
04162                                                        connection->disconnect_message_link);
04163       connection->disconnect_message_link = NULL;
04164 
04165       return DBUS_DISPATCH_DATA_REMAINS;
04166     }
04167 
04168   return DBUS_DISPATCH_COMPLETE;
04169 }
04170 
04171 static DBusDispatchStatus
04172 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04173 {
04174   HAVE_LOCK_CHECK (connection);
04175   
04176   if (connection->n_incoming > 0)
04177     return DBUS_DISPATCH_DATA_REMAINS;
04178   else if (!_dbus_transport_queue_messages (connection->transport))
04179     return DBUS_DISPATCH_NEED_MEMORY;
04180   else
04181     {
04182       DBusDispatchStatus status;
04183       dbus_bool_t is_connected;
04184       
04185       status = _dbus_transport_get_dispatch_status (connection->transport);
04186       is_connected = _dbus_transport_get_is_connected (connection->transport);
04187 
04188       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04189                      DISPATCH_STATUS_NAME (status), is_connected);
04190       
04191       if (!is_connected)
04192         {
04193           /* It's possible this would be better done by having an explicit
04194            * notification from _dbus_transport_disconnect() that would
04195            * synchronously do this, instead of waiting for the next dispatch
04196            * status check. However, probably not good to change until it causes
04197            * a problem.
04198            */
04199           notify_disconnected_unlocked (connection);
04200 
04201           /* I'm not sure this is needed; the idea is that we want to
04202            * queue the Disconnected only after we've read all the
04203            * messages, but if we're disconnected maybe we are guaranteed
04204            * to have read them all ?
04205            */
04206           if (status == DBUS_DISPATCH_COMPLETE)
04207             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04208         }
04209       
04210       if (status != DBUS_DISPATCH_COMPLETE)
04211         return status;
04212       else if (connection->n_incoming > 0)
04213         return DBUS_DISPATCH_DATA_REMAINS;
04214       else
04215         return DBUS_DISPATCH_COMPLETE;
04216     }
04217 }
04218 
04219 static void
04220 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04221                                                     DBusDispatchStatus new_status)
04222 {
04223   dbus_bool_t changed;
04224   DBusDispatchStatusFunction function;
04225   void *data;
04226 
04227   HAVE_LOCK_CHECK (connection);
04228 
04229   _dbus_connection_ref_unlocked (connection);
04230 
04231   changed = new_status != connection->last_dispatch_status;
04232 
04233   connection->last_dispatch_status = new_status;
04234 
04235   function = connection->dispatch_status_function;
04236   data = connection->dispatch_status_data;
04237 
04238   if (connection->disconnected_message_arrived &&
04239       !connection->disconnected_message_processed)
04240     {
04241       connection->disconnected_message_processed = TRUE;
04242       
04243       /* this does an unref, but we have a ref
04244        * so we should not run the finalizer here
04245        * inside the lock.
04246        */
04247       connection_forget_shared_unlocked (connection);
04248 
04249       if (connection->exit_on_disconnect)
04250         {
04251           CONNECTION_UNLOCK (connection);            
04252           
04253           _dbus_verbose ("Exiting on Disconnected signal\n");
04254           _dbus_exit (1);
04255           _dbus_assert_not_reached ("Call to exit() returned");
04256         }
04257     }
04258   
04259   /* We drop the lock */
04260   CONNECTION_UNLOCK (connection);
04261   
04262   if (changed && function)
04263     {
04264       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04265                      connection, new_status,
04266                      DISPATCH_STATUS_NAME (new_status));
04267       (* function) (connection, new_status, data);      
04268     }
04269   
04270   dbus_connection_unref (connection);
04271 }
04272 
04298 DBusDispatchStatus
04299 dbus_connection_get_dispatch_status (DBusConnection *connection)
04300 {
04301   DBusDispatchStatus status;
04302 
04303   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04304 
04305   _dbus_verbose ("start\n");
04306   
04307   CONNECTION_LOCK (connection);
04308 
04309   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04310   
04311   CONNECTION_UNLOCK (connection);
04312 
04313   return status;
04314 }
04315 
04319 static DBusHandlerResult
04320 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04321                                                  DBusMessage    *message)
04322 {
04323   dbus_bool_t sent = FALSE;
04324   DBusMessage *ret = NULL;
04325   DBusList *expire_link;
04326 
04327   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04328     {
04329       /* This means we're letting the bus route this message */
04330       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04331     }
04332 
04333   if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04334     {
04335       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04336     }
04337 
04338   /* Preallocate a linked-list link, so that if we need to dispose of a
04339    * message, we can attach it to the expired list */
04340   expire_link = _dbus_list_alloc_link (NULL);
04341 
04342   if (!expire_link)
04343     return DBUS_HANDLER_RESULT_NEED_MEMORY;
04344 
04345   if (dbus_message_is_method_call (message,
04346                                    DBUS_INTERFACE_PEER,
04347                                    "Ping"))
04348     {
04349       ret = dbus_message_new_method_return (message);
04350       if (ret == NULL)
04351         goto out;
04352 
04353       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04354     }
04355   else if (dbus_message_is_method_call (message,
04356                                         DBUS_INTERFACE_PEER,
04357                                         "GetMachineId"))
04358     {
04359       DBusString uuid;
04360       
04361       ret = dbus_message_new_method_return (message);
04362       if (ret == NULL)
04363         goto out;
04364 
04365       _dbus_string_init (&uuid);
04366       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04367         {
04368           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04369           if (dbus_message_append_args (ret,
04370                                         DBUS_TYPE_STRING, &v_STRING,
04371                                         DBUS_TYPE_INVALID))
04372             {
04373               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04374             }
04375         }
04376       _dbus_string_free (&uuid);
04377     }
04378   else
04379     {
04380       /* We need to bounce anything else with this interface, otherwise apps
04381        * could start extending the interface and when we added extensions
04382        * here to DBusConnection we'd break those apps.
04383        */
04384       ret = dbus_message_new_error (message,
04385                                     DBUS_ERROR_UNKNOWN_METHOD,
04386                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04387       if (ret == NULL)
04388         goto out;
04389 
04390       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04391     }
04392 
04393 out:
04394   if (ret == NULL)
04395     {
04396       _dbus_list_free_link (expire_link);
04397     }
04398   else
04399     {
04400       /* It'll be safe to unref the reply when we unlock */
04401       expire_link->data = ret;
04402       _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04403     }
04404 
04405   if (!sent)
04406     return DBUS_HANDLER_RESULT_NEED_MEMORY;
04407 
04408   return DBUS_HANDLER_RESULT_HANDLED;
04409 }
04410 
04417 static DBusHandlerResult
04418 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04419                                                            DBusMessage    *message)
04420 {
04421   /* We just run one filter for now but have the option to run more
04422      if the spec calls for it in the future */
04423 
04424   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04425 }
04426 
04469 DBusDispatchStatus
04470 dbus_connection_dispatch (DBusConnection *connection)
04471 {
04472   DBusMessage *message;
04473   DBusList *link, *filter_list_copy, *message_link;
04474   DBusHandlerResult result;
04475   DBusPendingCall *pending;
04476   dbus_int32_t reply_serial;
04477   DBusDispatchStatus status;
04478 
04479   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04480 
04481   _dbus_verbose ("\n");
04482   
04483   CONNECTION_LOCK (connection);
04484   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04485   if (status != DBUS_DISPATCH_DATA_REMAINS)
04486     {
04487       /* unlocks and calls out to user code */
04488       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04489       return status;
04490     }
04491   
04492   /* We need to ref the connection since the callback could potentially
04493    * drop the last ref to it
04494    */
04495   _dbus_connection_ref_unlocked (connection);
04496 
04497   _dbus_connection_acquire_dispatch (connection);
04498   HAVE_LOCK_CHECK (connection);
04499 
04500   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04501   if (message_link == NULL)
04502     {
04503       /* another thread dispatched our stuff */
04504 
04505       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04506       
04507       _dbus_connection_release_dispatch (connection);
04508 
04509       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04510 
04511       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04512       
04513       dbus_connection_unref (connection);
04514       
04515       return status;
04516     }
04517 
04518   message = message_link->data;
04519 
04520   _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04521                  message,
04522                  dbus_message_type_to_string (dbus_message_get_type (message)),
04523                  dbus_message_get_interface (message) ?
04524                  dbus_message_get_interface (message) :
04525                  "no interface",
04526                  dbus_message_get_member (message) ?
04527                  dbus_message_get_member (message) :
04528                  "no member",
04529                  dbus_message_get_signature (message));
04530 
04531   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04532   
04533   /* Pending call handling must be first, because if you do
04534    * dbus_connection_send_with_reply_and_block() or
04535    * dbus_pending_call_block() then no handlers/filters will be run on
04536    * the reply. We want consistent semantics in the case where we
04537    * dbus_connection_dispatch() the reply.
04538    */
04539   
04540   reply_serial = dbus_message_get_reply_serial (message);
04541   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04542                                          reply_serial);
04543   if (pending)
04544     {
04545       _dbus_verbose ("Dispatching a pending reply\n");
04546       complete_pending_call_and_unlock (connection, pending, message);
04547       pending = NULL; /* it's probably unref'd */
04548       
04549       CONNECTION_LOCK (connection);
04550       _dbus_verbose ("pending call completed in dispatch\n");
04551       result = DBUS_HANDLER_RESULT_HANDLED;
04552       goto out;
04553     }
04554 
04555   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04556   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04557     goto out;
04558  
04559   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04560     {
04561       _dbus_connection_release_dispatch (connection);
04562       HAVE_LOCK_CHECK (connection);
04563       
04564       _dbus_connection_failed_pop (connection, message_link);
04565 
04566       /* unlocks and calls user code */
04567       _dbus_connection_update_dispatch_status_and_unlock (connection,
04568                                                           DBUS_DISPATCH_NEED_MEMORY);
04569       dbus_connection_unref (connection);
04570       
04571       return DBUS_DISPATCH_NEED_MEMORY;
04572     }
04573   
04574   _dbus_list_foreach (&filter_list_copy,
04575                       (DBusForeachFunction)_dbus_message_filter_ref,
04576                       NULL);
04577 
04578   /* We're still protected from dispatch() reentrancy here
04579    * since we acquired the dispatcher
04580    */
04581   CONNECTION_UNLOCK (connection);
04582   
04583   link = _dbus_list_get_first_link (&filter_list_copy);
04584   while (link != NULL)
04585     {
04586       DBusMessageFilter *filter = link->data;
04587       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04588 
04589       if (filter->function == NULL)
04590         {
04591           _dbus_verbose ("  filter was removed in a callback function\n");
04592           link = next;
04593           continue;
04594         }
04595 
04596       _dbus_verbose ("  running filter on message %p\n", message);
04597       result = (* filter->function) (connection, message, filter->user_data);
04598 
04599       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04600         break;
04601 
04602       link = next;
04603     }
04604 
04605   _dbus_list_foreach (&filter_list_copy,
04606                       (DBusForeachFunction)_dbus_message_filter_unref,
04607                       NULL);
04608   _dbus_list_clear (&filter_list_copy);
04609   
04610   CONNECTION_LOCK (connection);
04611 
04612   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04613     {
04614       _dbus_verbose ("No memory\n");
04615       goto out;
04616     }
04617   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04618     {
04619       _dbus_verbose ("filter handled message in dispatch\n");
04620       goto out;
04621     }
04622 
04623   /* We're still protected from dispatch() reentrancy here
04624    * since we acquired the dispatcher
04625    */
04626   _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
04627                  message,
04628                  dbus_message_type_to_string (dbus_message_get_type (message)),
04629                  dbus_message_get_interface (message) ?
04630                  dbus_message_get_interface (message) :
04631                  "no interface",
04632                  dbus_message_get_member (message) ?
04633                  dbus_message_get_member (message) :
04634                  "no member",
04635                  dbus_message_get_signature (message));
04636 
04637   HAVE_LOCK_CHECK (connection);
04638   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04639                                                   message);
04640   
04641   CONNECTION_LOCK (connection);
04642 
04643   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04644     {
04645       _dbus_verbose ("object tree handled message in dispatch\n");
04646       goto out;
04647     }
04648 
04649   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04650     {
04651       DBusMessage *reply;
04652       DBusString str;
04653       DBusPreallocatedSend *preallocated;
04654       DBusList *expire_link;
04655 
04656       _dbus_verbose ("  sending error %s\n",
04657                      DBUS_ERROR_UNKNOWN_METHOD);
04658 
04659       if (!_dbus_string_init (&str))
04660         {
04661           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04662           _dbus_verbose ("no memory for error string in dispatch\n");
04663           goto out;
04664         }
04665               
04666       if (!_dbus_string_append_printf (&str,
04667                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04668                                        dbus_message_get_member (message),
04669                                        dbus_message_get_signature (message),
04670                                        dbus_message_get_interface (message)))
04671         {
04672           _dbus_string_free (&str);
04673           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04674           _dbus_verbose ("no memory for error string in dispatch\n");
04675           goto out;
04676         }
04677       
04678       reply = dbus_message_new_error (message,
04679                                       DBUS_ERROR_UNKNOWN_METHOD,
04680                                       _dbus_string_get_const_data (&str));
04681       _dbus_string_free (&str);
04682 
04683       if (reply == NULL)
04684         {
04685           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04686           _dbus_verbose ("no memory for error reply in dispatch\n");
04687           goto out;
04688         }
04689 
04690       expire_link = _dbus_list_alloc_link (reply);
04691 
04692       if (expire_link == NULL)
04693         {
04694           dbus_message_unref (reply);
04695           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04696           _dbus_verbose ("no memory for error send in dispatch\n");
04697           goto out;
04698         }
04699 
04700       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04701 
04702       if (preallocated == NULL)
04703         {
04704           _dbus_list_free_link (expire_link);
04705           /* It's OK that this is finalized, because it hasn't been seen by
04706            * anything that could attach user callbacks */
04707           dbus_message_unref (reply);
04708           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04709           _dbus_verbose ("no memory for error send in dispatch\n");
04710           goto out;
04711         }
04712 
04713       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04714                                                              reply, NULL);
04715       /* reply will be freed when we release the lock */
04716       _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04717 
04718       result = DBUS_HANDLER_RESULT_HANDLED;
04719     }
04720   
04721   _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04722                  dbus_message_type_to_string (dbus_message_get_type (message)),
04723                  dbus_message_get_interface (message) ?
04724                  dbus_message_get_interface (message) :
04725                  "no interface",
04726                  dbus_message_get_member (message) ?
04727                  dbus_message_get_member (message) :
04728                  "no member",
04729                  dbus_message_get_signature (message),
04730                  connection);
04731   
04732  out:
04733   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04734     {
04735       _dbus_verbose ("out of memory\n");
04736       
04737       /* Put message back, and we'll start over.
04738        * Yes this means handlers must be idempotent if they
04739        * don't return HANDLED; c'est la vie.
04740        */
04741       _dbus_connection_putback_message_link_unlocked (connection,
04742                                                       message_link);
04743       /* now we don't want to free them */
04744       message_link = NULL;
04745       message = NULL;
04746     }
04747   else
04748     {
04749       _dbus_verbose (" ... done dispatching\n");
04750     }
04751 
04752   _dbus_connection_release_dispatch (connection);
04753   HAVE_LOCK_CHECK (connection);
04754 
04755   if (message != NULL)
04756     {
04757       /* We don't want this message to count in maximum message limits when
04758        * computing the dispatch status, below. We have to drop the lock
04759        * temporarily, because finalizing a message can trigger callbacks.
04760        *
04761        * We have a reference to the connection, and we don't use any cached
04762        * pointers to the connection's internals below this point, so it should
04763        * be safe to drop the lock and take it back. */
04764       CONNECTION_UNLOCK (connection);
04765       dbus_message_unref (message);
04766       CONNECTION_LOCK (connection);
04767     }
04768 
04769   if (message_link != NULL)
04770     _dbus_list_free_link (message_link);
04771 
04772   _dbus_verbose ("before final status update\n");
04773   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04774 
04775   /* unlocks and calls user code */
04776   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04777   
04778   dbus_connection_unref (connection);
04779   
04780   return status;
04781 }
04782 
04844 dbus_bool_t
04845 dbus_connection_set_watch_functions (DBusConnection              *connection,
04846                                      DBusAddWatchFunction         add_function,
04847                                      DBusRemoveWatchFunction      remove_function,
04848                                      DBusWatchToggledFunction     toggled_function,
04849                                      void                        *data,
04850                                      DBusFreeFunction             free_data_function)
04851 {
04852   dbus_bool_t retval;
04853 
04854   _dbus_return_val_if_fail (connection != NULL, FALSE);
04855   
04856   CONNECTION_LOCK (connection);
04857 
04858   retval = _dbus_watch_list_set_functions (connection->watches,
04859                                            add_function, remove_function,
04860                                            toggled_function,
04861                                            data, free_data_function);
04862 
04863   CONNECTION_UNLOCK (connection);
04864 
04865   return retval;
04866 }
04867 
04907 dbus_bool_t
04908 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04909                                          DBusAddTimeoutFunction     add_function,
04910                                          DBusRemoveTimeoutFunction  remove_function,
04911                                          DBusTimeoutToggledFunction toggled_function,
04912                                          void                      *data,
04913                                          DBusFreeFunction           free_data_function)
04914 {
04915   dbus_bool_t retval;
04916 
04917   _dbus_return_val_if_fail (connection != NULL, FALSE);
04918   
04919   CONNECTION_LOCK (connection);
04920 
04921   retval = _dbus_timeout_list_set_functions (connection->timeouts,
04922                                              add_function, remove_function,
04923                                              toggled_function,
04924                                              data, free_data_function);
04925 
04926   CONNECTION_UNLOCK (connection);
04927 
04928   return retval;
04929 }
04930 
04945 void
04946 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04947                                           DBusWakeupMainFunction     wakeup_main_function,
04948                                           void                      *data,
04949                                           DBusFreeFunction           free_data_function)
04950 {
04951   void *old_data;
04952   DBusFreeFunction old_free_data;
04953 
04954   _dbus_return_if_fail (connection != NULL);
04955   
04956   CONNECTION_LOCK (connection);
04957   old_data = connection->wakeup_main_data;
04958   old_free_data = connection->free_wakeup_main_data;
04959 
04960   connection->wakeup_main_function = wakeup_main_function;
04961   connection->wakeup_main_data = data;
04962   connection->free_wakeup_main_data = free_data_function;
04963   
04964   CONNECTION_UNLOCK (connection);
04965 
04966   /* Callback outside the lock */
04967   if (old_free_data)
04968     (*old_free_data) (old_data);
04969 }
04970 
04991 void
04992 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04993                                               DBusDispatchStatusFunction  function,
04994                                               void                       *data,
04995                                               DBusFreeFunction            free_data_function)
04996 {
04997   void *old_data;
04998   DBusFreeFunction old_free_data;
04999 
05000   _dbus_return_if_fail (connection != NULL);
05001   
05002   CONNECTION_LOCK (connection);
05003   old_data = connection->dispatch_status_data;
05004   old_free_data = connection->free_dispatch_status_data;
05005 
05006   connection->dispatch_status_function = function;
05007   connection->dispatch_status_data = data;
05008   connection->free_dispatch_status_data = free_data_function;
05009   
05010   CONNECTION_UNLOCK (connection);
05011 
05012   /* Callback outside the lock */
05013   if (old_free_data)
05014     (*old_free_data) (old_data);
05015 }
05016 
05036 dbus_bool_t
05037 dbus_connection_get_unix_fd (DBusConnection *connection,
05038                              int            *fd)
05039 {
05040   _dbus_return_val_if_fail (connection != NULL, FALSE);
05041   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05042 
05043 #ifdef DBUS_WIN
05044   /* FIXME do this on a lower level */
05045   return FALSE;
05046 #endif
05047   
05048   return dbus_connection_get_socket(connection, fd);
05049 }
05050 
05066 dbus_bool_t
05067 dbus_connection_get_socket(DBusConnection              *connection,
05068                            int                         *fd)
05069 {
05070   dbus_bool_t retval;
05071 
05072   _dbus_return_val_if_fail (connection != NULL, FALSE);
05073   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05074   
05075   CONNECTION_LOCK (connection);
05076   
05077   retval = _dbus_transport_get_socket_fd (connection->transport,
05078                                           fd);
05079 
05080   CONNECTION_UNLOCK (connection);
05081 
05082   return retval;
05083 }
05084 
05085 
05108 dbus_bool_t
05109 dbus_connection_get_unix_user (DBusConnection *connection,
05110                                unsigned long  *uid)
05111 {
05112   dbus_bool_t result;
05113 
05114   _dbus_return_val_if_fail (connection != NULL, FALSE);
05115   _dbus_return_val_if_fail (uid != NULL, FALSE);
05116   
05117   CONNECTION_LOCK (connection);
05118 
05119   if (!_dbus_transport_get_is_authenticated (connection->transport))
05120     result = FALSE;
05121   else
05122     result = _dbus_transport_get_unix_user (connection->transport,
05123                                             uid);
05124 
05125 #ifdef DBUS_WIN
05126   _dbus_assert (!result);
05127 #endif
05128   
05129   CONNECTION_UNLOCK (connection);
05130 
05131   return result;
05132 }
05133 
05144 dbus_bool_t
05145 dbus_connection_get_unix_process_id (DBusConnection *connection,
05146                                      unsigned long  *pid)
05147 {
05148   dbus_bool_t result;
05149 
05150   _dbus_return_val_if_fail (connection != NULL, FALSE);
05151   _dbus_return_val_if_fail (pid != NULL, FALSE);
05152   
05153   CONNECTION_LOCK (connection);
05154 
05155   if (!_dbus_transport_get_is_authenticated (connection->transport))
05156     result = FALSE;
05157   else
05158     result = _dbus_transport_get_unix_process_id (connection->transport,
05159                                                   pid);
05160 
05161   CONNECTION_UNLOCK (connection);
05162 
05163   return result;
05164 }
05165 
05176 dbus_bool_t
05177 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05178                                             void          **data,
05179                                             dbus_int32_t   *data_size)
05180 {
05181   dbus_bool_t result;
05182 
05183   _dbus_return_val_if_fail (connection != NULL, FALSE);
05184   _dbus_return_val_if_fail (data != NULL, FALSE);
05185   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05186   
05187   CONNECTION_LOCK (connection);
05188 
05189   if (!_dbus_transport_get_is_authenticated (connection->transport))
05190     result = FALSE;
05191   else
05192     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05193                                                          data,
05194                                                          data_size);
05195   CONNECTION_UNLOCK (connection);
05196 
05197   return result;
05198 }
05199 
05222 void
05223 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05224                                         DBusAllowUnixUserFunction   function,
05225                                         void                       *data,
05226                                         DBusFreeFunction            free_data_function)
05227 {
05228   void *old_data = NULL;
05229   DBusFreeFunction old_free_function = NULL;
05230 
05231   _dbus_return_if_fail (connection != NULL);
05232   
05233   CONNECTION_LOCK (connection);
05234   _dbus_transport_set_unix_user_function (connection->transport,
05235                                           function, data, free_data_function,
05236                                           &old_data, &old_free_function);
05237   CONNECTION_UNLOCK (connection);
05238 
05239   if (old_free_function != NULL)
05240     (* old_free_function) (old_data);
05241 }
05242 
05274 dbus_bool_t
05275 dbus_connection_get_windows_user (DBusConnection             *connection,
05276                                   char                      **windows_sid_p)
05277 {
05278   dbus_bool_t result;
05279 
05280   _dbus_return_val_if_fail (connection != NULL, FALSE);
05281   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05282   
05283   CONNECTION_LOCK (connection);
05284 
05285   if (!_dbus_transport_get_is_authenticated (connection->transport))
05286     result = FALSE;
05287   else
05288     result = _dbus_transport_get_windows_user (connection->transport,
05289                                                windows_sid_p);
05290 
05291 #ifdef DBUS_UNIX
05292   _dbus_assert (!result);
05293 #endif
05294   
05295   CONNECTION_UNLOCK (connection);
05296 
05297   return result;
05298 }
05299 
05321 void
05322 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05323                                            DBusAllowWindowsUserFunction function,
05324                                            void                        *data,
05325                                            DBusFreeFunction             free_data_function)
05326 {
05327   void *old_data = NULL;
05328   DBusFreeFunction old_free_function = NULL;
05329 
05330   _dbus_return_if_fail (connection != NULL);
05331   
05332   CONNECTION_LOCK (connection);
05333   _dbus_transport_set_windows_user_function (connection->transport,
05334                                              function, data, free_data_function,
05335                                              &old_data, &old_free_function);
05336   CONNECTION_UNLOCK (connection);
05337 
05338   if (old_free_function != NULL)
05339     (* old_free_function) (old_data);
05340 }
05341 
05368 void
05369 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05370                                      dbus_bool_t                 value)
05371 {
05372   _dbus_return_if_fail (connection != NULL);
05373   
05374   CONNECTION_LOCK (connection);
05375   _dbus_transport_set_allow_anonymous (connection->transport, value);
05376   CONNECTION_UNLOCK (connection);
05377 }
05378 
05396 void
05397 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05398                                          dbus_bool_t                 value)
05399 {
05400   _dbus_return_if_fail (connection != NULL);
05401   
05402   CONNECTION_LOCK (connection);
05403   connection->route_peer_messages = TRUE;
05404   CONNECTION_UNLOCK (connection);
05405 }
05406 
05428 dbus_bool_t
05429 dbus_connection_add_filter (DBusConnection            *connection,
05430                             DBusHandleMessageFunction  function,
05431                             void                      *user_data,
05432                             DBusFreeFunction           free_data_function)
05433 {
05434   DBusMessageFilter *filter;
05435   
05436   _dbus_return_val_if_fail (connection != NULL, FALSE);
05437   _dbus_return_val_if_fail (function != NULL, FALSE);
05438 
05439   filter = dbus_new0 (DBusMessageFilter, 1);
05440   if (filter == NULL)
05441     return FALSE;
05442 
05443   _dbus_atomic_inc (&filter->refcount);
05444 
05445   CONNECTION_LOCK (connection);
05446 
05447   if (!_dbus_list_append (&connection->filter_list,
05448                           filter))
05449     {
05450       _dbus_message_filter_unref (filter);
05451       CONNECTION_UNLOCK (connection);
05452       return FALSE;
05453     }
05454 
05455   /* Fill in filter after all memory allocated,
05456    * so we don't run the free_user_data_function
05457    * if the add_filter() fails
05458    */
05459   
05460   filter->function = function;
05461   filter->user_data = user_data;
05462   filter->free_user_data_function = free_data_function;
05463         
05464   CONNECTION_UNLOCK (connection);
05465   return TRUE;
05466 }
05467 
05480 void
05481 dbus_connection_remove_filter (DBusConnection            *connection,
05482                                DBusHandleMessageFunction  function,
05483                                void                      *user_data)
05484 {
05485   DBusList *link;
05486   DBusMessageFilter *filter;
05487   
05488   _dbus_return_if_fail (connection != NULL);
05489   _dbus_return_if_fail (function != NULL);
05490   
05491   CONNECTION_LOCK (connection);
05492 
05493   filter = NULL;
05494   
05495   link = _dbus_list_get_last_link (&connection->filter_list);
05496   while (link != NULL)
05497     {
05498       filter = link->data;
05499 
05500       if (filter->function == function &&
05501           filter->user_data == user_data)
05502         {
05503           _dbus_list_remove_link (&connection->filter_list, link);
05504           filter->function = NULL;
05505           
05506           break;
05507         }
05508         
05509       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05510       filter = NULL;
05511     }
05512   
05513   CONNECTION_UNLOCK (connection);
05514 
05515 #ifndef DBUS_DISABLE_CHECKS
05516   if (filter == NULL)
05517     {
05518       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05519                                function, user_data);
05520       return;
05521     }
05522 #endif
05523   
05524   /* Call application code */
05525   if (filter->free_user_data_function)
05526     (* filter->free_user_data_function) (filter->user_data);
05527 
05528   filter->free_user_data_function = NULL;
05529   filter->user_data = NULL;
05530   
05531   _dbus_message_filter_unref (filter);
05532 }
05533 
05546 dbus_bool_t
05547 dbus_connection_try_register_object_path (DBusConnection              *connection,
05548                                           const char                  *path,
05549                                           const DBusObjectPathVTable  *vtable,
05550                                           void                        *user_data,
05551                                           DBusError                   *error)
05552 {
05553   char **decomposed_path;
05554   dbus_bool_t retval;
05555   
05556   _dbus_return_val_if_fail (connection != NULL, FALSE);
05557   _dbus_return_val_if_fail (path != NULL, FALSE);
05558   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05559   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05560 
05561   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05562     return FALSE;
05563 
05564   CONNECTION_LOCK (connection);
05565 
05566   retval = _dbus_object_tree_register (connection->objects,
05567                                        FALSE,
05568                                        (const char **) decomposed_path, vtable,
05569                                        user_data, error);
05570 
05571   CONNECTION_UNLOCK (connection);
05572 
05573   dbus_free_string_array (decomposed_path);
05574 
05575   return retval;
05576 }
05577 
05592 dbus_bool_t
05593 dbus_connection_register_object_path (DBusConnection              *connection,
05594                                       const char                  *path,
05595                                       const DBusObjectPathVTable  *vtable,
05596                                       void                        *user_data)
05597 {
05598   char **decomposed_path;
05599   dbus_bool_t retval;
05600   DBusError error = DBUS_ERROR_INIT;
05601 
05602   _dbus_return_val_if_fail (connection != NULL, FALSE);
05603   _dbus_return_val_if_fail (path != NULL, FALSE);
05604   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05605   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05606 
05607   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05608     return FALSE;
05609 
05610   CONNECTION_LOCK (connection);
05611 
05612   retval = _dbus_object_tree_register (connection->objects,
05613                                        FALSE,
05614                                        (const char **) decomposed_path, vtable,
05615                                        user_data, &error);
05616 
05617   CONNECTION_UNLOCK (connection);
05618 
05619   dbus_free_string_array (decomposed_path);
05620 
05621   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05622     {
05623       _dbus_warn ("%s\n", error.message);
05624       dbus_error_free (&error);
05625       return FALSE;
05626     }
05627 
05628   return retval;
05629 }
05630 
05645 dbus_bool_t
05646 dbus_connection_try_register_fallback (DBusConnection              *connection,
05647                                        const char                  *path,
05648                                        const DBusObjectPathVTable  *vtable,
05649                                        void                        *user_data,
05650                                        DBusError                   *error)
05651 {
05652   char **decomposed_path;
05653   dbus_bool_t retval;
05654 
05655   _dbus_return_val_if_fail (connection != NULL, FALSE);
05656   _dbus_return_val_if_fail (path != NULL, FALSE);
05657   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05658   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05659 
05660   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05661     return FALSE;
05662 
05663   CONNECTION_LOCK (connection);
05664 
05665   retval = _dbus_object_tree_register (connection->objects,
05666                                        TRUE,
05667                                        (const char **) decomposed_path, vtable,
05668                                        user_data, error);
05669 
05670   CONNECTION_UNLOCK (connection);
05671 
05672   dbus_free_string_array (decomposed_path);
05673 
05674   return retval;
05675 }
05676 
05693 dbus_bool_t
05694 dbus_connection_register_fallback (DBusConnection              *connection,
05695                                    const char                  *path,
05696                                    const DBusObjectPathVTable  *vtable,
05697                                    void                        *user_data)
05698 {
05699   char **decomposed_path;
05700   dbus_bool_t retval;
05701   DBusError error = DBUS_ERROR_INIT;
05702 
05703   _dbus_return_val_if_fail (connection != NULL, FALSE);
05704   _dbus_return_val_if_fail (path != NULL, FALSE);
05705   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05706   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05707 
05708   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05709     return FALSE;
05710 
05711   CONNECTION_LOCK (connection);
05712 
05713   retval = _dbus_object_tree_register (connection->objects,
05714                                        TRUE,
05715                                        (const char **) decomposed_path, vtable,
05716                                        user_data, &error);
05717 
05718   CONNECTION_UNLOCK (connection);
05719 
05720   dbus_free_string_array (decomposed_path);
05721 
05722   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05723     {
05724       _dbus_warn ("%s\n", error.message);
05725       dbus_error_free (&error);
05726       return FALSE;
05727     }
05728 
05729   return retval;
05730 }
05731 
05741 dbus_bool_t
05742 dbus_connection_unregister_object_path (DBusConnection              *connection,
05743                                         const char                  *path)
05744 {
05745   char **decomposed_path;
05746 
05747   _dbus_return_val_if_fail (connection != NULL, FALSE);
05748   _dbus_return_val_if_fail (path != NULL, FALSE);
05749   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05750 
05751   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05752       return FALSE;
05753 
05754   CONNECTION_LOCK (connection);
05755 
05756   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05757 
05758   dbus_free_string_array (decomposed_path);
05759 
05760   return TRUE;
05761 }
05762 
05773 dbus_bool_t
05774 dbus_connection_get_object_path_data (DBusConnection *connection,
05775                                       const char     *path,
05776                                       void          **data_p)
05777 {
05778   char **decomposed_path;
05779 
05780   _dbus_return_val_if_fail (connection != NULL, FALSE);
05781   _dbus_return_val_if_fail (path != NULL, FALSE);
05782   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05783 
05784   *data_p = NULL;
05785   
05786   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05787     return FALSE;
05788   
05789   CONNECTION_LOCK (connection);
05790 
05791   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05792 
05793   CONNECTION_UNLOCK (connection);
05794 
05795   dbus_free_string_array (decomposed_path);
05796 
05797   return TRUE;
05798 }
05799 
05810 dbus_bool_t
05811 dbus_connection_list_registered (DBusConnection              *connection,
05812                                  const char                  *parent_path,
05813                                  char                      ***child_entries)
05814 {
05815   char **decomposed_path;
05816   dbus_bool_t retval;
05817   _dbus_return_val_if_fail (connection != NULL, FALSE);
05818   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05819   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05820   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05821 
05822   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05823     return FALSE;
05824 
05825   CONNECTION_LOCK (connection);
05826 
05827   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05828                                                          (const char **) decomposed_path,
05829                                                          child_entries);
05830   dbus_free_string_array (decomposed_path);
05831 
05832   return retval;
05833 }
05834 
05835 static DBusDataSlotAllocator slot_allocator;
05836 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05837 
05852 dbus_bool_t
05853 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05854 {
05855   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05856                                           &_DBUS_LOCK_NAME (connection_slots),
05857                                           slot_p);
05858 }
05859 
05871 void
05872 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05873 {
05874   _dbus_return_if_fail (*slot_p >= 0);
05875   
05876   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05877 }
05878 
05901 dbus_bool_t
05902 dbus_connection_set_data (DBusConnection   *connection,
05903                           dbus_int32_t      slot,
05904                           void             *data,
05905                           DBusFreeFunction  free_data_func)
05906 {
05907   DBusFreeFunction old_free_func;
05908   void *old_data;
05909   dbus_bool_t retval;
05910 
05911   _dbus_return_val_if_fail (connection != NULL, FALSE);
05912   _dbus_return_val_if_fail (slot >= 0, FALSE);
05913   
05914   SLOTS_LOCK (connection);
05915 
05916   retval = _dbus_data_slot_list_set (&slot_allocator,
05917                                      &connection->slot_list,
05918                                      slot, data, free_data_func,
05919                                      &old_free_func, &old_data);
05920   
05921   SLOTS_UNLOCK (connection);
05922 
05923   if (retval)
05924     {
05925       /* Do the actual free outside the connection lock */
05926       if (old_free_func)
05927         (* old_free_func) (old_data);
05928     }
05929 
05930   return retval;
05931 }
05932 
05950 void*
05951 dbus_connection_get_data (DBusConnection   *connection,
05952                           dbus_int32_t      slot)
05953 {
05954   void *res;
05955 
05956   _dbus_return_val_if_fail (connection != NULL, NULL);
05957   
05958   SLOTS_LOCK (connection);
05959 
05960   res = _dbus_data_slot_list_get (&slot_allocator,
05961                                   &connection->slot_list,
05962                                   slot);
05963   
05964   SLOTS_UNLOCK (connection);
05965 
05966   return res;
05967 }
05968 
05975 void
05976 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05977 {  
05978   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05979 }
05980 
05989 void
05990 dbus_connection_set_max_message_size (DBusConnection *connection,
05991                                       long            size)
05992 {
05993   _dbus_return_if_fail (connection != NULL);
05994   
05995   CONNECTION_LOCK (connection);
05996   _dbus_transport_set_max_message_size (connection->transport,
05997                                         size);
05998   CONNECTION_UNLOCK (connection);
05999 }
06000 
06007 long
06008 dbus_connection_get_max_message_size (DBusConnection *connection)
06009 {
06010   long res;
06011 
06012   _dbus_return_val_if_fail (connection != NULL, 0);
06013   
06014   CONNECTION_LOCK (connection);
06015   res = _dbus_transport_get_max_message_size (connection->transport);
06016   CONNECTION_UNLOCK (connection);
06017   return res;
06018 }
06019 
06028 void
06029 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06030                                           long            n)
06031 {
06032   _dbus_return_if_fail (connection != NULL);
06033 
06034   CONNECTION_LOCK (connection);
06035   _dbus_transport_set_max_message_unix_fds (connection->transport,
06036                                             n);
06037   CONNECTION_UNLOCK (connection);
06038 }
06039 
06046 long
06047 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06048 {
06049   long res;
06050 
06051   _dbus_return_val_if_fail (connection != NULL, 0);
06052 
06053   CONNECTION_LOCK (connection);
06054   res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06055   CONNECTION_UNLOCK (connection);
06056   return res;
06057 }
06058 
06084 void
06085 dbus_connection_set_max_received_size (DBusConnection *connection,
06086                                        long            size)
06087 {
06088   _dbus_return_if_fail (connection != NULL);
06089   
06090   CONNECTION_LOCK (connection);
06091   _dbus_transport_set_max_received_size (connection->transport,
06092                                          size);
06093   CONNECTION_UNLOCK (connection);
06094 }
06095 
06102 long
06103 dbus_connection_get_max_received_size (DBusConnection *connection)
06104 {
06105   long res;
06106 
06107   _dbus_return_val_if_fail (connection != NULL, 0);
06108   
06109   CONNECTION_LOCK (connection);
06110   res = _dbus_transport_get_max_received_size (connection->transport);
06111   CONNECTION_UNLOCK (connection);
06112   return res;
06113 }
06114 
06126 void
06127 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06128                                            long            n)
06129 {
06130   _dbus_return_if_fail (connection != NULL);
06131 
06132   CONNECTION_LOCK (connection);
06133   _dbus_transport_set_max_received_unix_fds (connection->transport,
06134                                              n);
06135   CONNECTION_UNLOCK (connection);
06136 }
06137 
06144 long
06145 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06146 {
06147   long res;
06148 
06149   _dbus_return_val_if_fail (connection != NULL, 0);
06150 
06151   CONNECTION_LOCK (connection);
06152   res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06153   CONNECTION_UNLOCK (connection);
06154   return res;
06155 }
06156 
06167 long
06168 dbus_connection_get_outgoing_size (DBusConnection *connection)
06169 {
06170   long res;
06171 
06172   _dbus_return_val_if_fail (connection != NULL, 0);
06173 
06174   CONNECTION_LOCK (connection);
06175   res = _dbus_counter_get_size_value (connection->outgoing_counter);
06176   CONNECTION_UNLOCK (connection);
06177   return res;
06178 }
06179 
06187 long
06188 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06189 {
06190   long res;
06191 
06192   _dbus_return_val_if_fail (connection != NULL, 0);
06193 
06194   CONNECTION_LOCK (connection);
06195   res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06196   CONNECTION_UNLOCK (connection);
06197   return res;
06198 }
06199 

Generated on Fri Jul 11 2014 20:41:31 for D-Bus by  doxygen 1.7.1