dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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-threads.h"
00037 #include "dbus-protocol.h"
00038 #include "dbus-dataslot.h"
00039 #include "dbus-string.h"
00040 #include "dbus-pending-call.h"
00041 #include "dbus-object-tree.h"
00042 #include "dbus-threads-internal.h"
00043 #include "dbus-bus.h"
00044 
00045 #ifdef DBUS_DISABLE_CHECKS
00046 #define TOOK_LOCK_CHECK(connection)
00047 #define RELEASING_LOCK_CHECK(connection)
00048 #define HAVE_LOCK_CHECK(connection)
00049 #else
00050 #define TOOK_LOCK_CHECK(connection) do {                \
00051     _dbus_assert (!(connection)->have_connection_lock); \
00052     (connection)->have_connection_lock = TRUE;          \
00053   } while (0)
00054 #define RELEASING_LOCK_CHECK(connection) do {            \
00055     _dbus_assert ((connection)->have_connection_lock);   \
00056     (connection)->have_connection_lock = FALSE;          \
00057   } while (0)
00058 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00059 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00060 #endif
00061 
00062 #define TRACE_LOCKS 1
00063 
00064 #define CONNECTION_LOCK(connection)   do {                                      \
00065     if (TRACE_LOCKS) { _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME); }   \
00066     _dbus_mutex_lock ((connection)->mutex);                                      \
00067     TOOK_LOCK_CHECK (connection);                                               \
00068   } while (0)
00069 
00070 #define CONNECTION_UNLOCK(connection) do {                                              \
00071     if (TRACE_LOCKS) { _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);  }        \
00072     RELEASING_LOCK_CHECK (connection);                                                  \
00073     _dbus_mutex_unlock ((connection)->mutex);                                            \
00074   } while (0)
00075 
00076 #define DISPATCH_STATUS_NAME(s)                                            \
00077                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00078                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00079                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00080                       "???")
00081 
00202 typedef struct DBusMessageFilter DBusMessageFilter;
00203 
00207 struct DBusMessageFilter
00208 {
00209   DBusAtomic refcount; 
00210   DBusHandleMessageFunction function; 
00211   void *user_data; 
00212   DBusFreeFunction free_user_data_function; 
00213 };
00214 
00215 
00219 struct DBusPreallocatedSend
00220 {
00221   DBusConnection *connection; 
00222   DBusList *queue_link;       
00223   DBusList *counter_link;     
00224 };
00225 
00226 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00227 
00231 struct DBusConnection
00232 {
00233   DBusAtomic refcount; 
00235   DBusMutex *mutex; 
00237   DBusMutex *dispatch_mutex;     
00238   DBusCondVar *dispatch_cond;    
00239   DBusMutex *io_path_mutex;      
00240   DBusCondVar *io_path_cond;     
00242   DBusList *outgoing_messages; 
00243   DBusList *incoming_messages; 
00245   DBusMessage *message_borrowed; 
00249   int n_outgoing;              
00250   int n_incoming;              
00252   DBusCounter *outgoing_counter; 
00254   DBusTransport *transport;    
00255   DBusWatchList *watches;      
00256   DBusTimeoutList *timeouts;   
00258   DBusList *filter_list;        
00260   DBusDataSlotList slot_list;   
00262   DBusHashTable *pending_replies;  
00264   dbus_uint32_t client_serial;       
00265   DBusList *disconnect_message_link; 
00267   DBusWakeupMainFunction wakeup_main_function; 
00268   void *wakeup_main_data; 
00269   DBusFreeFunction free_wakeup_main_data; 
00271   DBusDispatchStatusFunction dispatch_status_function; 
00272   void *dispatch_status_data; 
00273   DBusFreeFunction free_dispatch_status_data; 
00275   DBusDispatchStatus last_dispatch_status; 
00277   DBusList *link_cache; 
00280   DBusObjectTree *objects; 
00282   char *server_guid; 
00284   unsigned int shareable : 1; 
00286   unsigned int dispatch_acquired : 1; 
00287   unsigned int io_path_acquired : 1;  
00289   unsigned int exit_on_disconnect : 1; 
00291   unsigned int route_peer_messages : 1; 
00293   unsigned int disconnected_message_arrived : 1;   
00297   unsigned int disconnected_message_processed : 1; 
00301 #ifndef DBUS_DISABLE_CHECKS
00302   unsigned int have_connection_lock : 1; 
00303 #endif
00304   
00305 #ifndef DBUS_DISABLE_CHECKS
00306   int generation; 
00307 #endif 
00308 };
00309 
00310 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00311 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00312                                                                               DBusDispatchStatus  new_status);
00313 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00314 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00315 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00316 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00317 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00318 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00319 
00320 static DBusMessageFilter *
00321 _dbus_message_filter_ref (DBusMessageFilter *filter)
00322 {
00323   _dbus_assert (filter->refcount.value > 0);
00324   _dbus_atomic_inc (&filter->refcount);
00325 
00326   return filter;
00327 }
00328 
00329 static void
00330 _dbus_message_filter_unref (DBusMessageFilter *filter)
00331 {
00332   _dbus_assert (filter->refcount.value > 0);
00333 
00334   if (_dbus_atomic_dec (&filter->refcount) == 1)
00335     {
00336       if (filter->free_user_data_function)
00337         (* filter->free_user_data_function) (filter->user_data);
00338       
00339       dbus_free (filter);
00340     }
00341 }
00342 
00348 void
00349 _dbus_connection_lock (DBusConnection *connection)
00350 {
00351   CONNECTION_LOCK (connection);
00352 }
00353 
00359 void
00360 _dbus_connection_unlock (DBusConnection *connection)
00361 {
00362   CONNECTION_UNLOCK (connection);
00363 }
00364 
00372 static void
00373 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00374 {
00375   if (connection->wakeup_main_function)
00376     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00377 }
00378 
00379 #ifdef DBUS_BUILD_TESTS
00380 /* For now this function isn't used */
00390 dbus_bool_t
00391 _dbus_connection_queue_received_message (DBusConnection *connection,
00392                                          DBusMessage    *message)
00393 {
00394   DBusList *link;
00395 
00396   link = _dbus_list_alloc_link (message);
00397   if (link == NULL)
00398     return FALSE;
00399 
00400   dbus_message_ref (message);
00401   _dbus_connection_queue_received_message_link (connection, link);
00402 
00403   return TRUE;
00404 }
00405 
00418 void 
00419 _dbus_connection_test_get_locks (DBusConnection *connection,
00420                                  DBusMutex     **mutex_loc,
00421                                  DBusMutex     **dispatch_mutex_loc,
00422                                  DBusMutex     **io_path_mutex_loc,
00423                                  DBusCondVar   **dispatch_cond_loc,
00424                                  DBusCondVar   **io_path_cond_loc)
00425 {
00426   *mutex_loc = connection->mutex;
00427   *dispatch_mutex_loc = connection->dispatch_mutex;
00428   *io_path_mutex_loc = connection->io_path_mutex; 
00429   *dispatch_cond_loc = connection->dispatch_cond;
00430   *io_path_cond_loc = connection->io_path_cond;
00431 }
00432 #endif
00433 
00442 void
00443 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00444                                               DBusList        *link)
00445 {
00446   DBusPendingCall *pending;
00447   dbus_int32_t reply_serial;
00448   DBusMessage *message;
00449   
00450   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00451   
00452   _dbus_list_append_link (&connection->incoming_messages,
00453                           link);
00454   message = link->data;
00455 
00456   /* If this is a reply we're waiting on, remove timeout for it */
00457   reply_serial = dbus_message_get_reply_serial (message);
00458   if (reply_serial != -1)
00459     {
00460       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00461                                              reply_serial);
00462       if (pending != NULL)
00463         {
00464           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00465             _dbus_connection_remove_timeout_unlocked (connection,
00466                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00467 
00468           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00469         }
00470     }
00471   
00472   
00473 
00474   connection->n_incoming += 1;
00475 
00476   _dbus_connection_wakeup_mainloop (connection);
00477   
00478   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00479                  message,
00480                  dbus_message_get_type (message),
00481                  dbus_message_get_path (message) ?
00482                  dbus_message_get_path (message) :
00483                  "no path",
00484                  dbus_message_get_interface (message) ?
00485                  dbus_message_get_interface (message) :
00486                  "no interface",
00487                  dbus_message_get_member (message) ?
00488                  dbus_message_get_member (message) :
00489                  "no member",
00490                  dbus_message_get_signature (message),
00491                  dbus_message_get_reply_serial (message),
00492                  connection,
00493                  connection->n_incoming);}
00494 
00503 void
00504 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00505                                                  DBusList *link)
00506 {
00507   HAVE_LOCK_CHECK (connection);
00508   
00509   _dbus_list_append_link (&connection->incoming_messages, link);
00510 
00511   connection->n_incoming += 1;
00512 
00513   _dbus_connection_wakeup_mainloop (connection);
00514   
00515   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00516                  link->data, connection, connection->n_incoming);
00517 }
00518 
00519 
00527 dbus_bool_t
00528 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00529 {
00530   HAVE_LOCK_CHECK (connection);
00531   return connection->outgoing_messages != NULL;
00532 }
00533 
00543 dbus_bool_t
00544 dbus_connection_has_messages_to_send (DBusConnection *connection)
00545 {
00546   dbus_bool_t v;
00547   
00548   _dbus_return_val_if_fail (connection != NULL, FALSE);
00549 
00550   CONNECTION_LOCK (connection);
00551   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00552   CONNECTION_UNLOCK (connection);
00553 
00554   return v;
00555 }
00556 
00564 DBusMessage*
00565 _dbus_connection_get_message_to_send (DBusConnection *connection)
00566 {
00567   HAVE_LOCK_CHECK (connection);
00568   
00569   return _dbus_list_get_last (&connection->outgoing_messages);
00570 }
00571 
00580 void
00581 _dbus_connection_message_sent (DBusConnection *connection,
00582                                DBusMessage    *message)
00583 {
00584   DBusList *link;
00585 
00586   HAVE_LOCK_CHECK (connection);
00587   
00588   /* This can be called before we even complete authentication, since
00589    * it's called on disconnect to clean up the outgoing queue.
00590    * It's also called as we successfully send each message.
00591    */
00592   
00593   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00594   _dbus_assert (link != NULL);
00595   _dbus_assert (link->data == message);
00596 
00597   /* Save this link in the link cache */
00598   _dbus_list_unlink (&connection->outgoing_messages,
00599                      link);
00600   _dbus_list_prepend_link (&connection->link_cache, link);
00601   
00602   connection->n_outgoing -= 1;
00603 
00604   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00605                  message,
00606                  dbus_message_get_type (message),
00607                  dbus_message_get_path (message) ?
00608                  dbus_message_get_path (message) :
00609                  "no path",
00610                  dbus_message_get_interface (message) ?
00611                  dbus_message_get_interface (message) :
00612                  "no interface",
00613                  dbus_message_get_member (message) ?
00614                  dbus_message_get_member (message) :
00615                  "no member",
00616                  dbus_message_get_signature (message),
00617                  connection, connection->n_outgoing);
00618 
00619   /* Save this link in the link cache also */
00620   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00621                                      &link);
00622   _dbus_list_prepend_link (&connection->link_cache, link);
00623   
00624   dbus_message_unref (message);
00625 }
00626 
00628 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00629                                                   DBusWatch     *watch);
00631 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00632                                                   DBusWatch     *watch);
00634 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00635                                                   DBusWatch     *watch,
00636                                                   dbus_bool_t    enabled);
00637 
00638 static dbus_bool_t
00639 protected_change_watch (DBusConnection         *connection,
00640                         DBusWatch              *watch,
00641                         DBusWatchAddFunction    add_function,
00642                         DBusWatchRemoveFunction remove_function,
00643                         DBusWatchToggleFunction toggle_function,
00644                         dbus_bool_t             enabled)
00645 {
00646   DBusWatchList *watches;
00647   dbus_bool_t retval;
00648   
00649   HAVE_LOCK_CHECK (connection);
00650 
00651   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00652    * drop lock and call out" one; but it has to be propagated up through all callers
00653    */
00654   
00655   watches = connection->watches;
00656   if (watches)
00657     {
00658       connection->watches = NULL;
00659       _dbus_connection_ref_unlocked (connection);
00660       CONNECTION_UNLOCK (connection);
00661 
00662       if (add_function)
00663         retval = (* add_function) (watches, watch);
00664       else if (remove_function)
00665         {
00666           retval = TRUE;
00667           (* remove_function) (watches, watch);
00668         }
00669       else
00670         {
00671           retval = TRUE;
00672           (* toggle_function) (watches, watch, enabled);
00673         }
00674       
00675       CONNECTION_LOCK (connection);
00676       connection->watches = watches;
00677       _dbus_connection_unref_unlocked (connection);
00678 
00679       return retval;
00680     }
00681   else
00682     return FALSE;
00683 }
00684      
00685 
00697 dbus_bool_t
00698 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00699                                      DBusWatch      *watch)
00700 {
00701   return protected_change_watch (connection, watch,
00702                                  _dbus_watch_list_add_watch,
00703                                  NULL, NULL, FALSE);
00704 }
00705 
00715 void
00716 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00717                                         DBusWatch      *watch)
00718 {
00719   protected_change_watch (connection, watch,
00720                           NULL,
00721                           _dbus_watch_list_remove_watch,
00722                           NULL, FALSE);
00723 }
00724 
00735 void
00736 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00737                                         DBusWatch      *watch,
00738                                         dbus_bool_t     enabled)
00739 {
00740   _dbus_assert (watch != NULL);
00741 
00742   protected_change_watch (connection, watch,
00743                           NULL, NULL,
00744                           _dbus_watch_list_toggle_watch,
00745                           enabled);
00746 }
00747 
00749 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00750                                                    DBusTimeout     *timeout);
00752 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00753                                                    DBusTimeout     *timeout);
00755 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00756                                                    DBusTimeout     *timeout,
00757                                                    dbus_bool_t      enabled);
00758 
00759 static dbus_bool_t
00760 protected_change_timeout (DBusConnection           *connection,
00761                           DBusTimeout              *timeout,
00762                           DBusTimeoutAddFunction    add_function,
00763                           DBusTimeoutRemoveFunction remove_function,
00764                           DBusTimeoutToggleFunction toggle_function,
00765                           dbus_bool_t               enabled)
00766 {
00767   DBusTimeoutList *timeouts;
00768   dbus_bool_t retval;
00769   
00770   HAVE_LOCK_CHECK (connection);
00771 
00772   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00773    * drop lock and call out" one; but it has to be propagated up through all callers
00774    */
00775   
00776   timeouts = connection->timeouts;
00777   if (timeouts)
00778     {
00779       connection->timeouts = NULL;
00780       _dbus_connection_ref_unlocked (connection);
00781       CONNECTION_UNLOCK (connection);
00782 
00783       if (add_function)
00784         retval = (* add_function) (timeouts, timeout);
00785       else if (remove_function)
00786         {
00787           retval = TRUE;
00788           (* remove_function) (timeouts, timeout);
00789         }
00790       else
00791         {
00792           retval = TRUE;
00793           (* toggle_function) (timeouts, timeout, enabled);
00794         }
00795       
00796       CONNECTION_LOCK (connection);
00797       connection->timeouts = timeouts;
00798       _dbus_connection_unref_unlocked (connection);
00799 
00800       return retval;
00801     }
00802   else
00803     return FALSE;
00804 }
00805 
00818 dbus_bool_t
00819 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00820                                        DBusTimeout    *timeout)
00821 {
00822   return protected_change_timeout (connection, timeout,
00823                                    _dbus_timeout_list_add_timeout,
00824                                    NULL, NULL, FALSE);
00825 }
00826 
00836 void
00837 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00838                                           DBusTimeout    *timeout)
00839 {
00840   protected_change_timeout (connection, timeout,
00841                             NULL,
00842                             _dbus_timeout_list_remove_timeout,
00843                             NULL, FALSE);
00844 }
00845 
00856 void
00857 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00858                                           DBusTimeout      *timeout,
00859                                           dbus_bool_t       enabled)
00860 {
00861   protected_change_timeout (connection, timeout,
00862                             NULL, NULL,
00863                             _dbus_timeout_list_toggle_timeout,
00864                             enabled);
00865 }
00866 
00867 static dbus_bool_t
00868 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00869                                                DBusPendingCall *pending)
00870 {
00871   dbus_uint32_t reply_serial;
00872   DBusTimeout *timeout;
00873 
00874   HAVE_LOCK_CHECK (connection);
00875 
00876   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00877 
00878   _dbus_assert (reply_serial != 0);
00879 
00880   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00881 
00882   if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00883     return FALSE;
00884   
00885   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00886                                     reply_serial,
00887                                     pending))
00888     {
00889       _dbus_connection_remove_timeout_unlocked (connection, timeout);
00890 
00891       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00892       HAVE_LOCK_CHECK (connection);
00893       return FALSE;
00894     }
00895   
00896   _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00897 
00898   _dbus_pending_call_ref_unlocked (pending);
00899 
00900   HAVE_LOCK_CHECK (connection);
00901   
00902   return TRUE;
00903 }
00904 
00905 static void
00906 free_pending_call_on_hash_removal (void *data)
00907 {
00908   DBusPendingCall *pending;
00909   DBusConnection  *connection;
00910   
00911   if (data == NULL)
00912     return;
00913 
00914   pending = data;
00915 
00916   connection = _dbus_pending_call_get_connection_unlocked (pending);
00917 
00918   HAVE_LOCK_CHECK (connection);
00919   
00920   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00921     {
00922       _dbus_connection_remove_timeout_unlocked (connection,
00923                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00924       
00925       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00926     }
00927 
00928   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00929    * here, but the pending call finalizer could in principle call out to 
00930    * application code so we pretty much have to... some larger code reorg 
00931    * might be needed.
00932    */
00933   _dbus_connection_ref_unlocked (connection);
00934   _dbus_pending_call_unref_and_unlock (pending);
00935   CONNECTION_LOCK (connection);
00936   _dbus_connection_unref_unlocked (connection);
00937 }
00938 
00939 static void
00940 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00941                                                DBusPendingCall *pending)
00942 {
00943   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00944    * say the least.
00945    */
00946   _dbus_hash_table_remove_int (connection->pending_replies,
00947                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00948 }
00949 
00950 static void
00951 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00952                                                  DBusPendingCall *pending)
00953 {
00954   /* The idea here is to avoid finalizing the pending call
00955    * with the lock held, since there's a destroy notifier
00956    * in pending call that goes out to application code.
00957    *
00958    * There's an extra unlock inside the hash table
00959    * "free pending call" function FIXME...
00960    */
00961   _dbus_pending_call_ref_unlocked (pending);
00962   _dbus_hash_table_remove_int (connection->pending_replies,
00963                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00964   _dbus_pending_call_unref_and_unlock (pending);
00965 }
00966 
00975 void
00976 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00977                                       DBusPendingCall *pending)
00978 {
00979   CONNECTION_LOCK (connection);
00980   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00981 }
00982 
00992 static dbus_bool_t
00993 _dbus_connection_acquire_io_path (DBusConnection *connection,
00994                                   int             timeout_milliseconds)
00995 {
00996   dbus_bool_t we_acquired;
00997   
00998   HAVE_LOCK_CHECK (connection);
00999 
01000   /* We don't want the connection to vanish */
01001   _dbus_connection_ref_unlocked (connection);
01002 
01003   /* We will only touch io_path_acquired which is protected by our mutex */
01004   CONNECTION_UNLOCK (connection);
01005   
01006   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01007   _dbus_mutex_lock (connection->io_path_mutex);
01008 
01009   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01010                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01011 
01012   we_acquired = FALSE;
01013   
01014   if (connection->io_path_acquired)
01015     {
01016       if (timeout_milliseconds != -1)
01017         {
01018           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01019                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
01020 
01021           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01022                                            connection->io_path_mutex,
01023                                            timeout_milliseconds))
01024             {
01025               /* We timed out before anyone signaled. */
01026               /* (writing the loop to handle the !timedout case by
01027                * waiting longer if needed is a pain since dbus
01028                * wraps pthread_cond_timedwait to take a relative
01029                * time instead of absolute, something kind of stupid
01030                * on our part. for now it doesn't matter, we will just
01031                * end up back here eventually.)
01032                */
01033             }
01034         }
01035       else
01036         {
01037           while (connection->io_path_acquired)
01038             {
01039               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01040               _dbus_condvar_wait (connection->io_path_cond, 
01041                                   connection->io_path_mutex);
01042             }
01043         }
01044     }
01045   
01046   if (!connection->io_path_acquired)
01047     {
01048       we_acquired = TRUE;
01049       connection->io_path_acquired = TRUE;
01050     }
01051   
01052   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01053                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01054 
01055   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01056   _dbus_mutex_unlock (connection->io_path_mutex);
01057 
01058   CONNECTION_LOCK (connection);
01059   
01060   HAVE_LOCK_CHECK (connection);
01061 
01062   _dbus_connection_unref_unlocked (connection);
01063   
01064   return we_acquired;
01065 }
01066 
01074 static void
01075 _dbus_connection_release_io_path (DBusConnection *connection)
01076 {
01077   HAVE_LOCK_CHECK (connection);
01078   
01079   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01080   _dbus_mutex_lock (connection->io_path_mutex);
01081   
01082   _dbus_assert (connection->io_path_acquired);
01083 
01084   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01085                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01086   
01087   connection->io_path_acquired = FALSE;
01088   _dbus_condvar_wake_one (connection->io_path_cond);
01089 
01090   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01091   _dbus_mutex_unlock (connection->io_path_mutex);
01092 }
01093 
01122 void
01123 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01124                                         unsigned int    flags,
01125                                         int             timeout_milliseconds)
01126 {
01127   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01128   
01129   HAVE_LOCK_CHECK (connection);
01130   
01131   if (connection->n_outgoing == 0)
01132     flags &= ~DBUS_ITERATION_DO_WRITING;
01133 
01134   if (_dbus_connection_acquire_io_path (connection,
01135                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01136     {
01137       HAVE_LOCK_CHECK (connection);
01138       
01139       _dbus_transport_do_iteration (connection->transport,
01140                                     flags, timeout_milliseconds);
01141       _dbus_connection_release_io_path (connection);
01142     }
01143 
01144   HAVE_LOCK_CHECK (connection);
01145 
01146   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01147 }
01148 
01158 DBusConnection*
01159 _dbus_connection_new_for_transport (DBusTransport *transport)
01160 {
01161   DBusConnection *connection;
01162   DBusWatchList *watch_list;
01163   DBusTimeoutList *timeout_list;
01164   DBusHashTable *pending_replies;
01165   DBusList *disconnect_link;
01166   DBusMessage *disconnect_message;
01167   DBusCounter *outgoing_counter;
01168   DBusObjectTree *objects;
01169   
01170   watch_list = NULL;
01171   connection = NULL;
01172   pending_replies = NULL;
01173   timeout_list = NULL;
01174   disconnect_link = NULL;
01175   disconnect_message = NULL;
01176   outgoing_counter = NULL;
01177   objects = NULL;
01178   
01179   watch_list = _dbus_watch_list_new ();
01180   if (watch_list == NULL)
01181     goto error;
01182 
01183   timeout_list = _dbus_timeout_list_new ();
01184   if (timeout_list == NULL)
01185     goto error;  
01186 
01187   pending_replies =
01188     _dbus_hash_table_new (DBUS_HASH_INT,
01189                           NULL,
01190                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01191   if (pending_replies == NULL)
01192     goto error;
01193   
01194   connection = dbus_new0 (DBusConnection, 1);
01195   if (connection == NULL)
01196     goto error;
01197 
01198   _dbus_mutex_new_at_location (&connection->mutex);
01199   if (connection->mutex == NULL)
01200     goto error;
01201 
01202   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01203   if (connection->io_path_mutex == NULL)
01204     goto error;
01205 
01206   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01207   if (connection->dispatch_mutex == NULL)
01208     goto error;
01209   
01210   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01211   if (connection->dispatch_cond == NULL)
01212     goto error;
01213   
01214   _dbus_condvar_new_at_location (&connection->io_path_cond);
01215   if (connection->io_path_cond == NULL)
01216     goto error;
01217 
01218   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01219                                                 DBUS_INTERFACE_LOCAL,
01220                                                 "Disconnected");
01221   
01222   if (disconnect_message == NULL)
01223     goto error;
01224 
01225   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01226   if (disconnect_link == NULL)
01227     goto error;
01228 
01229   outgoing_counter = _dbus_counter_new ();
01230   if (outgoing_counter == NULL)
01231     goto error;
01232 
01233   objects = _dbus_object_tree_new (connection);
01234   if (objects == NULL)
01235     goto error;
01236   
01237   if (_dbus_modify_sigpipe)
01238     _dbus_disable_sigpipe ();
01239   
01240   connection->refcount.value = 1;
01241   connection->transport = transport;
01242   connection->watches = watch_list;
01243   connection->timeouts = timeout_list;
01244   connection->pending_replies = pending_replies;
01245   connection->outgoing_counter = outgoing_counter;
01246   connection->filter_list = NULL;
01247   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01248   connection->objects = objects;
01249   connection->exit_on_disconnect = FALSE;
01250   connection->shareable = FALSE;
01251   connection->route_peer_messages = FALSE;
01252   connection->disconnected_message_arrived = FALSE;
01253   connection->disconnected_message_processed = FALSE;
01254   
01255 #ifndef DBUS_DISABLE_CHECKS
01256   connection->generation = _dbus_current_generation;
01257 #endif
01258   
01259   _dbus_data_slot_list_init (&connection->slot_list);
01260 
01261   connection->client_serial = 1;
01262 
01263   connection->disconnect_message_link = disconnect_link;
01264 
01265   CONNECTION_LOCK (connection);
01266   
01267   if (!_dbus_transport_set_connection (transport, connection))
01268     {
01269       CONNECTION_UNLOCK (connection);
01270 
01271       goto error;
01272     }
01273 
01274   _dbus_transport_ref (transport);
01275 
01276   CONNECTION_UNLOCK (connection);
01277   
01278   return connection;
01279   
01280  error:
01281   if (disconnect_message != NULL)
01282     dbus_message_unref (disconnect_message);
01283   
01284   if (disconnect_link != NULL)
01285     _dbus_list_free_link (disconnect_link);
01286   
01287   if (connection != NULL)
01288     {
01289       _dbus_condvar_free_at_location (&connection->io_path_cond);
01290       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01291       _dbus_mutex_free_at_location (&connection->mutex);
01292       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01293       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01294       dbus_free (connection);
01295     }
01296   if (pending_replies)
01297     _dbus_hash_table_unref (pending_replies);
01298   
01299   if (watch_list)
01300     _dbus_watch_list_free (watch_list);
01301 
01302   if (timeout_list)
01303     _dbus_timeout_list_free (timeout_list);
01304 
01305   if (outgoing_counter)
01306     _dbus_counter_unref (outgoing_counter);
01307 
01308   if (objects)
01309     _dbus_object_tree_unref (objects);
01310   
01311   return NULL;
01312 }
01313 
01321 DBusConnection *
01322 _dbus_connection_ref_unlocked (DBusConnection *connection)
01323 {  
01324   _dbus_assert (connection != NULL);
01325   _dbus_assert (connection->generation == _dbus_current_generation);
01326 
01327   HAVE_LOCK_CHECK (connection);
01328   
01329 #ifdef DBUS_HAVE_ATOMIC_INT
01330   _dbus_atomic_inc (&connection->refcount);
01331 #else
01332   _dbus_assert (connection->refcount.value > 0);
01333   connection->refcount.value += 1;
01334 #endif
01335 
01336   return connection;
01337 }
01338 
01345 void
01346 _dbus_connection_unref_unlocked (DBusConnection *connection)
01347 {
01348   dbus_bool_t last_unref;
01349 
01350   HAVE_LOCK_CHECK (connection);
01351   
01352   _dbus_assert (connection != NULL);
01353 
01354   /* The connection lock is better than the global
01355    * lock in the atomic increment fallback
01356    */
01357   
01358 #ifdef DBUS_HAVE_ATOMIC_INT
01359   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01360 #else
01361   _dbus_assert (connection->refcount.value > 0);
01362 
01363   connection->refcount.value -= 1;
01364   last_unref = (connection->refcount.value == 0);  
01365 #if 0
01366   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01367 #endif
01368 #endif
01369   
01370   if (last_unref)
01371     _dbus_connection_last_unref (connection);
01372 }
01373 
01374 static dbus_uint32_t
01375 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01376 {
01377   int serial;
01378 
01379   serial = connection->client_serial++;
01380 
01381   if (connection->client_serial < 0)
01382     connection->client_serial = 1;
01383   
01384   return serial;
01385 }
01386 
01400 dbus_bool_t
01401 _dbus_connection_handle_watch (DBusWatch                   *watch,
01402                                unsigned int                 condition,
01403                                void                        *data)
01404 {
01405   DBusConnection *connection;
01406   dbus_bool_t retval;
01407   DBusDispatchStatus status;
01408 
01409   connection = data;
01410 
01411   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01412   
01413   CONNECTION_LOCK (connection);
01414   _dbus_connection_acquire_io_path (connection, -1);
01415   HAVE_LOCK_CHECK (connection);
01416   retval = _dbus_transport_handle_watch (connection->transport,
01417                                          watch, condition);
01418 
01419   _dbus_connection_release_io_path (connection);
01420 
01421   HAVE_LOCK_CHECK (connection);
01422 
01423   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01424   
01425   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01426 
01427   /* this calls out to user code */
01428   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01429 
01430   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01431   
01432   return retval;
01433 }
01434 
01435 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01436 static DBusHashTable *shared_connections = NULL;
01437 
01438 static void
01439 shared_connections_shutdown (void *data)
01440 {
01441   int n_entries;
01442   
01443   _DBUS_LOCK (shared_connections);
01444   
01445   /* This is a little bit unpleasant... better ideas? */
01446   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01447     {
01448       DBusConnection *connection;
01449       DBusMessage *message;
01450       DBusHashIter iter;
01451       
01452       _dbus_hash_iter_init (shared_connections, &iter);
01453       _dbus_hash_iter_next (&iter);
01454        
01455       connection = _dbus_hash_iter_get_value (&iter);
01456 
01457       _DBUS_UNLOCK (shared_connections);
01458 
01459       dbus_connection_ref (connection);
01460       _dbus_connection_close_possibly_shared (connection);
01461 
01462       /* Churn through to the Disconnected message */
01463       while ((message = dbus_connection_pop_message (connection)))
01464         {
01465           dbus_message_unref (message);
01466         }
01467       dbus_connection_unref (connection);
01468       
01469       _DBUS_LOCK (shared_connections);
01470 
01471       /* The connection should now be dead and not in our hash ... */
01472       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01473     }
01474 
01475   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01476   
01477   _dbus_hash_table_unref (shared_connections);
01478   shared_connections = NULL;
01479   
01480   _DBUS_UNLOCK (shared_connections);
01481 }
01482 
01483 static dbus_bool_t
01484 connection_lookup_shared (DBusAddressEntry  *entry,
01485                           DBusConnection   **result)
01486 {
01487   _dbus_verbose ("checking for existing connection\n");
01488   
01489   *result = NULL;
01490   
01491   _DBUS_LOCK (shared_connections);
01492 
01493   if (shared_connections == NULL)
01494     {
01495       _dbus_verbose ("creating shared_connections hash table\n");
01496       
01497       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01498                                                  dbus_free,
01499                                                  NULL);
01500       if (shared_connections == NULL)
01501         {
01502           _DBUS_UNLOCK (shared_connections);
01503           return FALSE;
01504         }
01505 
01506       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01507         {
01508           _dbus_hash_table_unref (shared_connections);
01509           shared_connections = NULL;
01510           _DBUS_UNLOCK (shared_connections);
01511           return FALSE;
01512         }
01513 
01514       _dbus_verbose ("  successfully created shared_connections\n");
01515       
01516       _DBUS_UNLOCK (shared_connections);
01517       return TRUE; /* no point looking up in the hash we just made */
01518     }
01519   else
01520     {
01521       const char *guid;
01522 
01523       guid = dbus_address_entry_get_value (entry, "guid");
01524       
01525       if (guid != NULL)
01526         {
01527           DBusConnection *connection;
01528           
01529           connection = _dbus_hash_table_lookup_string (shared_connections,
01530                                                        guid);
01531 
01532           if (connection)
01533             {
01534               /* The DBusConnection can't be finalized without taking
01535                * the shared_connections lock to remove it from the
01536                * hash.  So it's safe to ref the connection here.
01537                * However, it may be disconnected if the Disconnected
01538                * message hasn't been processed yet, in which case we
01539                * want to pretend it isn't in the hash and avoid
01540                * returning it.
01541                *
01542                * The idea is to avoid ever returning a disconnected connection
01543                * from dbus_connection_open(). We could just synchronously
01544                * drop our shared ref to the connection on connection disconnect,
01545                * and then assert here that the connection is connected, but
01546                * that causes reentrancy headaches.
01547                */
01548               CONNECTION_LOCK (connection);
01549               if (_dbus_connection_get_is_connected_unlocked (connection))
01550                 {
01551                   _dbus_connection_ref_unlocked (connection);
01552                   *result = connection;
01553                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01554                                  guid);
01555                 }
01556               else
01557                 {
01558                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01559                                  guid);
01560                 }
01561               CONNECTION_UNLOCK (connection);
01562             }
01563         }
01564       
01565       _DBUS_UNLOCK (shared_connections);
01566       return TRUE;
01567     }
01568 }
01569 
01570 static dbus_bool_t
01571 connection_record_shared_unlocked (DBusConnection *connection,
01572                                    const char     *guid)
01573 {
01574   char *guid_key;
01575   char *guid_in_connection;
01576 
01577   HAVE_LOCK_CHECK (connection);
01578   _dbus_assert (connection->server_guid == NULL);
01579   _dbus_assert (connection->shareable);
01580 
01581   /* get a hard ref on this connection, even if
01582    * we won't in fact store it in the hash, we still
01583    * need to hold a ref on it until it's disconnected.
01584    */
01585   _dbus_connection_ref_unlocked (connection);
01586 
01587   if (guid == NULL)
01588     return TRUE; /* don't store in the hash */
01589   
01590   /* A separate copy of the key is required in the hash table, because
01591    * we don't have a lock on the connection when we are doing a hash
01592    * lookup.
01593    */
01594   
01595   guid_key = _dbus_strdup (guid);
01596   if (guid_key == NULL)
01597     return FALSE;
01598 
01599   guid_in_connection = _dbus_strdup (guid);
01600   if (guid_in_connection == NULL)
01601     {
01602       dbus_free (guid_key);
01603       return FALSE;
01604     }
01605   
01606   _DBUS_LOCK (shared_connections);
01607   _dbus_assert (shared_connections != NULL);
01608   
01609   if (!_dbus_hash_table_insert_string (shared_connections,
01610                                        guid_key, connection))
01611     {
01612       dbus_free (guid_key);
01613       dbus_free (guid_in_connection);
01614       _DBUS_UNLOCK (shared_connections);
01615       return FALSE;
01616     }
01617 
01618   connection->server_guid = guid_in_connection;
01619 
01620   _dbus_verbose ("stored connection to %s to be shared\n",
01621                  connection->server_guid);
01622   
01623   _DBUS_UNLOCK (shared_connections);
01624 
01625   _dbus_assert (connection->server_guid != NULL);
01626   
01627   return TRUE;
01628 }
01629 
01630 static void
01631 connection_forget_shared_unlocked (DBusConnection *connection)
01632 {
01633   HAVE_LOCK_CHECK (connection);
01634 
01635   if (!connection->shareable)
01636     return;
01637   
01638   if (connection->server_guid != NULL)
01639     {
01640       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01641                      connection->server_guid);
01642       
01643       _DBUS_LOCK (shared_connections);
01644       
01645       if (!_dbus_hash_table_remove_string (shared_connections,
01646                                            connection->server_guid))
01647         _dbus_assert_not_reached ("connection was not in the shared table");
01648       
01649       dbus_free (connection->server_guid);
01650       connection->server_guid = NULL;
01651       _DBUS_UNLOCK (shared_connections);
01652     }
01653   
01654   /* remove our reference held on all shareable connections */
01655   _dbus_connection_unref_unlocked (connection);
01656 }
01657 
01658 static DBusConnection*
01659 connection_try_from_address_entry (DBusAddressEntry *entry,
01660                                    DBusError        *error)
01661 {
01662   DBusTransport *transport;
01663   DBusConnection *connection;
01664 
01665   transport = _dbus_transport_open (entry, error);
01666 
01667   if (transport == NULL)
01668     {
01669       _DBUS_ASSERT_ERROR_IS_SET (error);
01670       return NULL;
01671     }
01672 
01673   connection = _dbus_connection_new_for_transport (transport);
01674 
01675   _dbus_transport_unref (transport);
01676   
01677   if (connection == NULL)
01678     {
01679       _DBUS_SET_OOM (error);
01680       return NULL;
01681     }
01682 
01683 #ifndef DBUS_DISABLE_CHECKS
01684   _dbus_assert (!connection->have_connection_lock);
01685 #endif
01686   return connection;
01687 }
01688 
01689 /*
01690  * If the shared parameter is true, then any existing connection will
01691  * be used (and if a new connection is created, it will be available
01692  * for use by others). If the shared parameter is false, a new
01693  * connection will always be created, and the new connection will
01694  * never be returned to other callers.
01695  *
01696  * @param address the address
01697  * @param shared whether the connection is shared or private
01698  * @param error error return
01699  * @returns the connection or #NULL on error
01700  */
01701 static DBusConnection*
01702 _dbus_connection_open_internal (const char     *address,
01703                                 dbus_bool_t     shared,
01704                                 DBusError      *error)
01705 {
01706   DBusConnection *connection;
01707   DBusAddressEntry **entries;
01708   DBusError tmp_error;
01709   DBusError first_error;
01710   int len, i;
01711 
01712   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01713 
01714   _dbus_verbose ("opening %s connection to: %s\n",
01715                  shared ? "shared" : "private", address);
01716   
01717   if (!dbus_parse_address (address, &entries, &len, error))
01718     return NULL;
01719 
01720   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01721   
01722   connection = NULL;
01723 
01724   dbus_error_init (&tmp_error);
01725   dbus_error_init (&first_error);
01726   for (i = 0; i < len; i++)
01727     {
01728       if (shared)
01729         {
01730           if (!connection_lookup_shared (entries[i], &connection))
01731             _DBUS_SET_OOM (&tmp_error);
01732         }
01733 
01734       if (connection == NULL)
01735         {
01736           connection = connection_try_from_address_entry (entries[i],
01737                                                           &tmp_error);
01738 
01739           if (connection != NULL && shared)
01740             {
01741               const char *guid;
01742                   
01743               connection->shareable = TRUE;
01744                   
01745               /* guid may be NULL */
01746               guid = dbus_address_entry_get_value (entries[i], "guid");
01747                   
01748               CONNECTION_LOCK (connection);
01749           
01750               if (!connection_record_shared_unlocked (connection, guid))
01751                 {
01752                   _DBUS_SET_OOM (&tmp_error);
01753                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01754                   dbus_connection_unref (connection);
01755                   connection = NULL;
01756                 }
01757               else
01758                 CONNECTION_UNLOCK (connection);
01759             }
01760         }
01761       
01762       if (connection)
01763         break;
01764 
01765       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01766       
01767       if (i == 0)
01768         dbus_move_error (&tmp_error, &first_error);
01769       else
01770         dbus_error_free (&tmp_error);
01771     }
01772   
01773   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01774   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01775   
01776   if (connection == NULL)
01777     {
01778       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01779       dbus_move_error (&first_error, error);
01780     }
01781   else
01782     dbus_error_free (&first_error);
01783   
01784   dbus_address_entries_free (entries);
01785   return connection;
01786 }
01787 
01796 void
01797 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01798 {
01799   _dbus_assert (connection != NULL);
01800   _dbus_assert (connection->generation == _dbus_current_generation);
01801 
01802   CONNECTION_LOCK (connection);
01803   _dbus_connection_close_possibly_shared_and_unlock (connection);
01804 }
01805 
01806 static DBusPreallocatedSend*
01807 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01808 {
01809   DBusPreallocatedSend *preallocated;
01810 
01811   HAVE_LOCK_CHECK (connection);
01812   
01813   _dbus_assert (connection != NULL);
01814   
01815   preallocated = dbus_new (DBusPreallocatedSend, 1);
01816   if (preallocated == NULL)
01817     return NULL;
01818 
01819   if (connection->link_cache != NULL)
01820     {
01821       preallocated->queue_link =
01822         _dbus_list_pop_first_link (&connection->link_cache);
01823       preallocated->queue_link->data = NULL;
01824     }
01825   else
01826     {
01827       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01828       if (preallocated->queue_link == NULL)
01829         goto failed_0;
01830     }
01831   
01832   if (connection->link_cache != NULL)
01833     {
01834       preallocated->counter_link =
01835         _dbus_list_pop_first_link (&connection->link_cache);
01836       preallocated->counter_link->data = connection->outgoing_counter;
01837     }
01838   else
01839     {
01840       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01841       if (preallocated->counter_link == NULL)
01842         goto failed_1;
01843     }
01844 
01845   _dbus_counter_ref (preallocated->counter_link->data);
01846 
01847   preallocated->connection = connection;
01848   
01849   return preallocated;
01850   
01851  failed_1:
01852   _dbus_list_free_link (preallocated->queue_link);
01853  failed_0:
01854   dbus_free (preallocated);
01855   
01856   return NULL;
01857 }
01858 
01859 /* Called with lock held, does not update dispatch status */
01860 static void
01861 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01862                                                        DBusPreallocatedSend *preallocated,
01863                                                        DBusMessage          *message,
01864                                                        dbus_uint32_t        *client_serial)
01865 {
01866   dbus_uint32_t serial;
01867   const char *sig;
01868 
01869   preallocated->queue_link->data = message;
01870   _dbus_list_prepend_link (&connection->outgoing_messages,
01871                            preallocated->queue_link);
01872 
01873   _dbus_message_add_size_counter_link (message,
01874                                        preallocated->counter_link);
01875 
01876   dbus_free (preallocated);
01877   preallocated = NULL;
01878   
01879   dbus_message_ref (message);
01880   
01881   connection->n_outgoing += 1;
01882 
01883   sig = dbus_message_get_signature (message);
01884   
01885   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01886                  message,
01887                  dbus_message_get_type (message),
01888                  dbus_message_get_path (message) ?
01889                  dbus_message_get_path (message) :
01890                  "no path",
01891                  dbus_message_get_interface (message) ?
01892                  dbus_message_get_interface (message) :
01893                  "no interface",
01894                  dbus_message_get_member (message) ?
01895                  dbus_message_get_member (message) :
01896                  "no member",
01897                  sig,
01898                  dbus_message_get_destination (message) ?
01899                  dbus_message_get_destination (message) :
01900                  "null",
01901                  connection,
01902                  connection->n_outgoing);
01903 
01904   if (dbus_message_get_serial (message) == 0)
01905     {
01906       serial = _dbus_connection_get_next_client_serial (connection);
01907       _dbus_message_set_serial (message, serial);
01908       if (client_serial)
01909         *client_serial = serial;
01910     }
01911   else
01912     {
01913       if (client_serial)
01914         *client_serial = dbus_message_get_serial (message);
01915     }
01916 
01917   _dbus_verbose ("Message %p serial is %u\n",
01918                  message, dbus_message_get_serial (message));
01919   
01920   _dbus_message_lock (message);
01921 
01922   /* Now we need to run an iteration to hopefully just write the messages
01923    * out immediately, and otherwise get them queued up
01924    */
01925   _dbus_connection_do_iteration_unlocked (connection,
01926                                           DBUS_ITERATION_DO_WRITING,
01927                                           -1);
01928 
01929   /* If stuff is still queued up, be sure we wake up the main loop */
01930   if (connection->n_outgoing > 0)
01931     _dbus_connection_wakeup_mainloop (connection);
01932 }
01933 
01934 static void
01935 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
01936                                                DBusPreallocatedSend *preallocated,
01937                                                DBusMessage          *message,
01938                                                dbus_uint32_t        *client_serial)
01939 {
01940   DBusDispatchStatus status;
01941 
01942   HAVE_LOCK_CHECK (connection);
01943   
01944   _dbus_connection_send_preallocated_unlocked_no_update (connection,
01945                                                          preallocated,
01946                                                          message, client_serial);
01947 
01948   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01949   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01950 
01951   /* this calls out to user code */
01952   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01953 }
01954 
01964 dbus_bool_t
01965 _dbus_connection_send_and_unlock (DBusConnection *connection,
01966                                   DBusMessage    *message,
01967                                   dbus_uint32_t  *client_serial)
01968 {
01969   DBusPreallocatedSend *preallocated;
01970 
01971   _dbus_assert (connection != NULL);
01972   _dbus_assert (message != NULL);
01973   
01974   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01975   if (preallocated == NULL)
01976     {
01977       CONNECTION_UNLOCK (connection);
01978       return FALSE;
01979     }
01980 
01981   _dbus_connection_send_preallocated_and_unlock (connection,
01982                                                  preallocated,
01983                                                  message,
01984                                                  client_serial);
01985   return TRUE;
01986 }
01987 
02012 void
02013 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02014 {
02015   CONNECTION_LOCK (connection);
02016   
02017   _dbus_assert (connection->refcount.value > 0);
02018 
02019   if (connection->refcount.value == 1)
02020     _dbus_connection_close_possibly_shared_and_unlock (connection);
02021   else
02022     CONNECTION_UNLOCK (connection);
02023 }
02024 
02025 
02035 static void
02036 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02037 {
02038   if (timeout_milliseconds == -1)
02039     _dbus_sleep_milliseconds (1000);
02040   else if (timeout_milliseconds < 100)
02041     ; /* just busy loop */
02042   else if (timeout_milliseconds <= 1000)
02043     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02044   else
02045     _dbus_sleep_milliseconds (1000);
02046 }
02047 
02048 static DBusMessage *
02049 generate_local_error_message (dbus_uint32_t serial, 
02050                               char *error_name, 
02051                               char *error_msg)
02052 {
02053   DBusMessage *message;
02054   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02055   if (!message)
02056     goto out;
02057 
02058   if (!dbus_message_set_error_name (message, error_name))
02059     {
02060       dbus_message_unref (message);
02061       message = NULL;
02062       goto out; 
02063     }
02064 
02065   dbus_message_set_no_reply (message, TRUE); 
02066 
02067   if (!dbus_message_set_reply_serial (message,
02068                                       serial))
02069     {
02070       dbus_message_unref (message);
02071       message = NULL;
02072       goto out;
02073     }
02074 
02075   if (error_msg != NULL)
02076     {
02077       DBusMessageIter iter;
02078 
02079       dbus_message_iter_init_append (message, &iter);
02080       if (!dbus_message_iter_append_basic (&iter,
02081                                            DBUS_TYPE_STRING,
02082                                            &error_msg))
02083         {
02084           dbus_message_unref (message);
02085           message = NULL;
02086           goto out;
02087         }
02088     }
02089 
02090  out:
02091   return message;
02092 }
02093 
02094 
02095 /* This is slightly strange since we can pop a message here without
02096  * the dispatch lock.
02097  */
02098 static DBusMessage*
02099 check_for_reply_unlocked (DBusConnection *connection,
02100                           dbus_uint32_t   client_serial)
02101 {
02102   DBusList *link;
02103 
02104   HAVE_LOCK_CHECK (connection);
02105   
02106   link = _dbus_list_get_first_link (&connection->incoming_messages);
02107 
02108   while (link != NULL)
02109     {
02110       DBusMessage *reply = link->data;
02111 
02112       if (dbus_message_get_reply_serial (reply) == client_serial)
02113         {
02114           _dbus_list_remove_link (&connection->incoming_messages, link);
02115           connection->n_incoming  -= 1;
02116           return reply;
02117         }
02118       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02119     }
02120 
02121   return NULL;
02122 }
02123 
02124 static void
02125 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02126 {
02127    /* We can't iterate over the hash in the normal way since we'll be
02128     * dropping the lock for each item. So we restart the
02129     * iter each time as we drain the hash table.
02130     */
02131    
02132    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02133     {
02134       DBusPendingCall *pending;
02135       DBusHashIter iter;
02136       
02137       _dbus_hash_iter_init (connection->pending_replies, &iter);
02138       _dbus_hash_iter_next (&iter);
02139        
02140       pending = _dbus_hash_iter_get_value (&iter);
02141       _dbus_pending_call_ref_unlocked (pending);
02142        
02143       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02144                                                        connection);
02145       _dbus_connection_remove_timeout_unlocked (connection,
02146                                                 _dbus_pending_call_get_timeout_unlocked (pending));
02147       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02148       _dbus_hash_iter_remove_entry (&iter);
02149 
02150       _dbus_pending_call_unref_and_unlock (pending);
02151       CONNECTION_LOCK (connection);
02152     }
02153   HAVE_LOCK_CHECK (connection);
02154 }
02155 
02156 static void
02157 complete_pending_call_and_unlock (DBusConnection  *connection,
02158                                   DBusPendingCall *pending,
02159                                   DBusMessage     *message)
02160 {
02161   _dbus_pending_call_set_reply_unlocked (pending, message);
02162   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02163   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02164  
02165   /* Must be called unlocked since it invokes app callback */
02166   _dbus_pending_call_complete (pending);
02167   dbus_pending_call_unref (pending);
02168 }
02169 
02170 static dbus_bool_t
02171 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02172                                               DBusPendingCall *pending)
02173 {
02174   DBusMessage *reply;
02175   DBusDispatchStatus status;
02176 
02177   reply = check_for_reply_unlocked (connection, 
02178                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02179   if (reply != NULL)
02180     {
02181       _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02182 
02183       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02184 
02185       complete_pending_call_and_unlock (connection, pending, reply);
02186       dbus_message_unref (reply);
02187 
02188       CONNECTION_LOCK (connection);
02189       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02190       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02191       dbus_pending_call_unref (pending);
02192 
02193       return TRUE;
02194     }
02195 
02196   return FALSE;
02197 }
02198 
02213 void
02214 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02215 {
02216   long start_tv_sec, start_tv_usec;
02217   long end_tv_sec, end_tv_usec;
02218   long tv_sec, tv_usec;
02219   DBusDispatchStatus status;
02220   DBusConnection *connection;
02221   dbus_uint32_t client_serial;
02222   int timeout_milliseconds;
02223 
02224   _dbus_assert (pending != NULL);
02225 
02226   if (dbus_pending_call_get_completed (pending))
02227     return;
02228 
02229   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02230 
02231   connection = _dbus_pending_call_get_connection_and_lock (pending);
02232   
02233   /* Flush message queue - note, can affect dispatch status */
02234   _dbus_connection_flush_unlocked (connection);
02235 
02236   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02237 
02238   /* note that timeout_milliseconds is limited to a smallish value
02239    * in _dbus_pending_call_new() so overflows aren't possible
02240    * below
02241    */
02242   timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02243   
02244   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02245   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02246   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02247   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02248   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02249 
02250   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n",
02251                  timeout_milliseconds,
02252                  client_serial,
02253                  start_tv_sec, start_tv_usec,
02254                  end_tv_sec, end_tv_usec);
02255 
02256   /* check to see if we already got the data off the socket */
02257   /* from another blocked pending call */
02258   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02259     return;
02260 
02261   /* Now we wait... */
02262   /* always block at least once as we know we don't have the reply yet */
02263   _dbus_connection_do_iteration_unlocked (connection,
02264                                           DBUS_ITERATION_DO_READING |
02265                                           DBUS_ITERATION_BLOCK,
02266                                           timeout_milliseconds);
02267 
02268  recheck_status:
02269 
02270   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02271   
02272   HAVE_LOCK_CHECK (connection);
02273   
02274   /* queue messages and get status */
02275 
02276   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02277 
02278   /* the get_completed() is in case a dispatch() while we were blocking
02279    * got the reply instead of us.
02280    */
02281   if (_dbus_pending_call_get_completed_unlocked (pending))
02282     {
02283       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02284       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02285       dbus_pending_call_unref (pending);
02286       return;
02287     }
02288   
02289   if (status == DBUS_DISPATCH_DATA_REMAINS) {
02290     if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02291       return;
02292   }
02293   
02294   _dbus_get_current_time (&tv_sec, &tv_usec);
02295   
02296   if (!_dbus_connection_get_is_connected_unlocked (connection))
02297     {
02298       DBusMessage *error_msg;
02299 
02300       error_msg = generate_local_error_message (client_serial,
02301                                                 DBUS_ERROR_DISCONNECTED, 
02302                                                 "Connection was disconnected before a reply was received"); 
02303 
02304       /* on OOM error_msg is set to NULL */
02305       complete_pending_call_and_unlock (connection, pending, error_msg);
02306       dbus_pending_call_unref (pending);
02307       return;
02308     }
02309   else if (tv_sec < start_tv_sec)
02310     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02311   else if (connection->disconnect_message_link == NULL)
02312     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02313   else if (tv_sec < end_tv_sec ||
02314            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02315     {
02316       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02317         (end_tv_usec - tv_usec) / 1000;
02318       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02319       _dbus_assert (timeout_milliseconds >= 0);
02320       
02321       if (status == DBUS_DISPATCH_NEED_MEMORY)
02322         {
02323           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02324            * we may already have a reply in the buffer and just can't process
02325            * it.
02326            */
02327           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02328 
02329           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02330         }
02331       else
02332         {          
02333           /* block again, we don't have the reply buffered yet. */
02334           _dbus_connection_do_iteration_unlocked (connection,
02335                                                   DBUS_ITERATION_DO_READING |
02336                                                   DBUS_ITERATION_BLOCK,
02337                                                   timeout_milliseconds);
02338         }
02339 
02340       goto recheck_status;
02341     }
02342 
02343   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02344                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02345 
02346   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02347   
02348   /* unlock and call user code */
02349   complete_pending_call_and_unlock (connection, pending, NULL);
02350 
02351   /* update user code on dispatch status */
02352   CONNECTION_LOCK (connection);
02353   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02354   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02355   dbus_pending_call_unref (pending);
02356 }
02357 
02394 DBusConnection*
02395 dbus_connection_open (const char     *address,
02396                       DBusError      *error)
02397 {
02398   DBusConnection *connection;
02399 
02400   _dbus_return_val_if_fail (address != NULL, NULL);
02401   _dbus_return_val_if_error_is_set (error, NULL);
02402 
02403   connection = _dbus_connection_open_internal (address,
02404                                                TRUE,
02405                                                error);
02406 
02407   return connection;
02408 }
02409 
02437 DBusConnection*
02438 dbus_connection_open_private (const char     *address,
02439                               DBusError      *error)
02440 {
02441   DBusConnection *connection;
02442 
02443   _dbus_return_val_if_fail (address != NULL, NULL);
02444   _dbus_return_val_if_error_is_set (error, NULL);
02445 
02446   connection = _dbus_connection_open_internal (address,
02447                                                FALSE,
02448                                                error);
02449 
02450   return connection;
02451 }
02452 
02459 DBusConnection *
02460 dbus_connection_ref (DBusConnection *connection)
02461 {
02462   _dbus_return_val_if_fail (connection != NULL, NULL);
02463   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02464   
02465   /* The connection lock is better than the global
02466    * lock in the atomic increment fallback
02467    */
02468   
02469 #ifdef DBUS_HAVE_ATOMIC_INT
02470   _dbus_atomic_inc (&connection->refcount);
02471 #else
02472   CONNECTION_LOCK (connection);
02473   _dbus_assert (connection->refcount.value > 0);
02474 
02475   connection->refcount.value += 1;
02476   CONNECTION_UNLOCK (connection);
02477 #endif
02478 
02479   return connection;
02480 }
02481 
02482 static void
02483 free_outgoing_message (void *element,
02484                        void *data)
02485 {
02486   DBusMessage *message = element;
02487   DBusConnection *connection = data;
02488 
02489   _dbus_message_remove_size_counter (message,
02490                                      connection->outgoing_counter,
02491                                      NULL);
02492   dbus_message_unref (message);
02493 }
02494 
02495 /* This is run without the mutex held, but after the last reference
02496  * to the connection has been dropped we should have no thread-related
02497  * problems
02498  */
02499 static void
02500 _dbus_connection_last_unref (DBusConnection *connection)
02501 {
02502   DBusList *link;
02503 
02504   _dbus_verbose ("Finalizing connection %p\n", connection);
02505   
02506   _dbus_assert (connection->refcount.value == 0);
02507   
02508   /* You have to disconnect the connection before unref:ing it. Otherwise
02509    * you won't get the disconnected message.
02510    */
02511   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02512   _dbus_assert (connection->server_guid == NULL);
02513   
02514   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02515   _dbus_object_tree_free_all_unlocked (connection->objects);
02516   
02517   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02518   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02519   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02520   
02521   _dbus_watch_list_free (connection->watches);
02522   connection->watches = NULL;
02523   
02524   _dbus_timeout_list_free (connection->timeouts);
02525   connection->timeouts = NULL;
02526 
02527   _dbus_data_slot_list_free (&connection->slot_list);
02528   
02529   link = _dbus_list_get_first_link (&connection->filter_list);
02530   while (link != NULL)
02531     {
02532       DBusMessageFilter *filter = link->data;
02533       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02534 
02535       filter->function = NULL;
02536       _dbus_message_filter_unref (filter); /* calls app callback */
02537       link->data = NULL;
02538       
02539       link = next;
02540     }
02541   _dbus_list_clear (&connection->filter_list);
02542   
02543   /* ---- Done with stuff that invokes application callbacks */
02544 
02545   _dbus_object_tree_unref (connection->objects);  
02546 
02547   _dbus_hash_table_unref (connection->pending_replies);
02548   connection->pending_replies = NULL;
02549   
02550   _dbus_list_clear (&connection->filter_list);
02551   
02552   _dbus_list_foreach (&connection->outgoing_messages,
02553                       free_outgoing_message,
02554                       connection);
02555   _dbus_list_clear (&connection->outgoing_messages);
02556   
02557   _dbus_list_foreach (&connection->incoming_messages,
02558                       (DBusForeachFunction) dbus_message_unref,
02559                       NULL);
02560   _dbus_list_clear (&connection->incoming_messages);
02561 
02562   _dbus_counter_unref (connection->outgoing_counter);
02563 
02564   _dbus_transport_unref (connection->transport);
02565 
02566   if (connection->disconnect_message_link)
02567     {
02568       DBusMessage *message = connection->disconnect_message_link->data;
02569       dbus_message_unref (message);
02570       _dbus_list_free_link (connection->disconnect_message_link);
02571     }
02572 
02573   _dbus_list_clear (&connection->link_cache);
02574   
02575   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02576   _dbus_condvar_free_at_location (&connection->io_path_cond);
02577 
02578   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02579   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02580 
02581   _dbus_mutex_free_at_location (&connection->mutex);
02582   
02583   dbus_free (connection);
02584 }
02585 
02605 void
02606 dbus_connection_unref (DBusConnection *connection)
02607 {
02608   dbus_bool_t last_unref;
02609 
02610   _dbus_return_if_fail (connection != NULL);
02611   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02612   
02613   /* The connection lock is better than the global
02614    * lock in the atomic increment fallback
02615    */
02616   
02617 #ifdef DBUS_HAVE_ATOMIC_INT
02618   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02619 #else
02620   CONNECTION_LOCK (connection);
02621   
02622   _dbus_assert (connection->refcount.value > 0);
02623 
02624   connection->refcount.value -= 1;
02625   last_unref = (connection->refcount.value == 0);
02626 
02627 #if 0
02628   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02629 #endif
02630   
02631   CONNECTION_UNLOCK (connection);
02632 #endif
02633   
02634   if (last_unref)
02635     {
02636 #ifndef DBUS_DISABLE_CHECKS
02637       if (_dbus_transport_get_is_connected (connection->transport))
02638         {
02639           _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",
02640                                    connection->shareable ?
02641                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02642                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02643           return;
02644         }
02645 #endif
02646       _dbus_connection_last_unref (connection);
02647     }
02648 }
02649 
02650 /*
02651  * Note that the transport can disconnect itself (other end drops us)
02652  * and in that case this function never runs. So this function must
02653  * not do anything more than disconnect the transport and update the
02654  * dispatch status.
02655  * 
02656  * If the transport self-disconnects, then we assume someone will
02657  * dispatch the connection to cause the dispatch status update.
02658  */
02659 static void
02660 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02661 {
02662   DBusDispatchStatus status;
02663 
02664   HAVE_LOCK_CHECK (connection);
02665   
02666   _dbus_verbose ("Disconnecting %p\n", connection);
02667 
02668   /* We need to ref because update_dispatch_status_and_unlock will unref
02669    * the connection if it was shared and libdbus was the only remaining
02670    * refcount holder.
02671    */
02672   _dbus_connection_ref_unlocked (connection);
02673   
02674   _dbus_transport_disconnect (connection->transport);
02675 
02676   /* This has the side effect of queuing the disconnect message link
02677    * (unless we don't have enough memory, possibly, so don't assert it).
02678    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02679    * should never again return the newly-disconnected connection.
02680    *
02681    * However, we only unref the shared connection and exit_on_disconnect when
02682    * the disconnect message reaches the head of the message queue,
02683    * NOT when it's first queued.
02684    */
02685   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02686 
02687   /* This calls out to user code */
02688   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02689 
02690   /* Could also call out to user code */
02691   dbus_connection_unref (connection);
02692 }
02693 
02736 void
02737 dbus_connection_close (DBusConnection *connection)
02738 {
02739   _dbus_return_if_fail (connection != NULL);
02740   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02741 
02742   CONNECTION_LOCK (connection);
02743 
02744 #ifndef DBUS_DISABLE_CHECKS
02745   if (connection->shareable)
02746     {
02747       CONNECTION_UNLOCK (connection);
02748 
02749       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02750       return;
02751     }
02752 #endif
02753   
02754   _dbus_connection_close_possibly_shared_and_unlock (connection);
02755 }
02756 
02757 static dbus_bool_t
02758 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02759 {
02760   HAVE_LOCK_CHECK (connection);
02761   return _dbus_transport_get_is_connected (connection->transport);
02762 }
02763 
02777 dbus_bool_t
02778 dbus_connection_get_is_connected (DBusConnection *connection)
02779 {
02780   dbus_bool_t res;
02781 
02782   _dbus_return_val_if_fail (connection != NULL, FALSE);
02783   
02784   CONNECTION_LOCK (connection);
02785   res = _dbus_connection_get_is_connected_unlocked (connection);
02786   CONNECTION_UNLOCK (connection);
02787   
02788   return res;
02789 }
02790 
02799 dbus_bool_t
02800 dbus_connection_get_is_authenticated (DBusConnection *connection)
02801 {
02802   dbus_bool_t res;
02803 
02804   _dbus_return_val_if_fail (connection != NULL, FALSE);
02805   
02806   CONNECTION_LOCK (connection);
02807   res = _dbus_transport_get_is_authenticated (connection->transport);
02808   CONNECTION_UNLOCK (connection);
02809   
02810   return res;
02811 }
02812 
02826 void
02827 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02828                                         dbus_bool_t     exit_on_disconnect)
02829 {
02830   _dbus_return_if_fail (connection != NULL);
02831 
02832   CONNECTION_LOCK (connection);
02833   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02834   CONNECTION_UNLOCK (connection);
02835 }
02836 
02846 DBusPreallocatedSend*
02847 dbus_connection_preallocate_send (DBusConnection *connection)
02848 {
02849   DBusPreallocatedSend *preallocated;
02850 
02851   _dbus_return_val_if_fail (connection != NULL, NULL);
02852 
02853   CONNECTION_LOCK (connection);
02854   
02855   preallocated =
02856     _dbus_connection_preallocate_send_unlocked (connection);
02857 
02858   CONNECTION_UNLOCK (connection);
02859 
02860   return preallocated;
02861 }
02862 
02872 void
02873 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02874                                         DBusPreallocatedSend *preallocated)
02875 {
02876   _dbus_return_if_fail (connection != NULL);
02877   _dbus_return_if_fail (preallocated != NULL);  
02878   _dbus_return_if_fail (connection == preallocated->connection);
02879 
02880   _dbus_list_free_link (preallocated->queue_link);
02881   _dbus_counter_unref (preallocated->counter_link->data);
02882   _dbus_list_free_link (preallocated->counter_link);
02883   dbus_free (preallocated);
02884 }
02885 
02898 void
02899 dbus_connection_send_preallocated (DBusConnection       *connection,
02900                                    DBusPreallocatedSend *preallocated,
02901                                    DBusMessage          *message,
02902                                    dbus_uint32_t        *client_serial)
02903 {
02904   _dbus_return_if_fail (connection != NULL);
02905   _dbus_return_if_fail (preallocated != NULL);
02906   _dbus_return_if_fail (message != NULL);
02907   _dbus_return_if_fail (preallocated->connection == connection);
02908   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02909                         dbus_message_get_member (message) != NULL);
02910   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02911                         (dbus_message_get_interface (message) != NULL &&
02912                          dbus_message_get_member (message) != NULL));
02913   
02914   CONNECTION_LOCK (connection);
02915   _dbus_connection_send_preallocated_and_unlock (connection,
02916                                                  preallocated,
02917                                                  message, client_serial);
02918 }
02919 
02920 static dbus_bool_t
02921 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02922                                           DBusMessage    *message,
02923                                           dbus_uint32_t  *client_serial)
02924 {
02925   DBusPreallocatedSend *preallocated;
02926 
02927   _dbus_assert (connection != NULL);
02928   _dbus_assert (message != NULL);
02929   
02930   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02931   if (preallocated == NULL)
02932     return FALSE;
02933 
02934   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02935                                                          preallocated,
02936                                                          message,
02937                                                          client_serial);
02938   return TRUE;
02939 }
02940 
02962 dbus_bool_t
02963 dbus_connection_send (DBusConnection *connection,
02964                       DBusMessage    *message,
02965                       dbus_uint32_t  *serial)
02966 {
02967   _dbus_return_val_if_fail (connection != NULL, FALSE);
02968   _dbus_return_val_if_fail (message != NULL, FALSE);
02969 
02970   CONNECTION_LOCK (connection);
02971 
02972   return _dbus_connection_send_and_unlock (connection,
02973                                            message,
02974                                            serial);
02975 }
02976 
02977 static dbus_bool_t
02978 reply_handler_timeout (void *data)
02979 {
02980   DBusConnection *connection;
02981   DBusDispatchStatus status;
02982   DBusPendingCall *pending = data;
02983 
02984   connection = _dbus_pending_call_get_connection_and_lock (pending);
02985 
02986   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02987                                                    connection);
02988   _dbus_connection_remove_timeout_unlocked (connection,
02989                                             _dbus_pending_call_get_timeout_unlocked (pending));
02990   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02991 
02992   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02993   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02994 
02995   /* Unlocks, and calls out to user code */
02996   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02997   
02998   return TRUE;
02999 }
03000 
03038 dbus_bool_t
03039 dbus_connection_send_with_reply (DBusConnection     *connection,
03040                                  DBusMessage        *message,
03041                                  DBusPendingCall   **pending_return,
03042                                  int                 timeout_milliseconds)
03043 {
03044   DBusPendingCall *pending;
03045   dbus_int32_t serial = -1;
03046   DBusDispatchStatus status;
03047 
03048   _dbus_return_val_if_fail (connection != NULL, FALSE);
03049   _dbus_return_val_if_fail (message != NULL, FALSE);
03050   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03051 
03052   if (pending_return)
03053     *pending_return = NULL;
03054 
03055   CONNECTION_LOCK (connection);
03056 
03057    if (!_dbus_connection_get_is_connected_unlocked (connection))
03058     {
03059       CONNECTION_UNLOCK (connection);
03060 
03061       *pending_return = NULL;
03062 
03063       return TRUE;
03064     }
03065 
03066   pending = _dbus_pending_call_new_unlocked (connection,
03067                                              timeout_milliseconds,
03068                                              reply_handler_timeout);
03069 
03070   if (pending == NULL)
03071     {
03072       CONNECTION_UNLOCK (connection);
03073       return FALSE;
03074     }
03075 
03076   /* Assign a serial to the message */
03077   serial = dbus_message_get_serial (message);
03078   if (serial == 0)
03079     {
03080       serial = _dbus_connection_get_next_client_serial (connection);
03081       _dbus_message_set_serial (message, serial);
03082     }
03083 
03084   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03085     goto error;
03086     
03087   /* Insert the serial in the pending replies hash;
03088    * hash takes a refcount on DBusPendingCall.
03089    * Also, add the timeout.
03090    */
03091   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03092                                                       pending))
03093     goto error;
03094  
03095   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03096     {
03097       _dbus_connection_detach_pending_call_and_unlock (connection,
03098                                                        pending);
03099       goto error_unlocked;
03100     }
03101 
03102   if (pending_return)
03103     *pending_return = pending; /* hand off refcount */
03104   else
03105     {
03106       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03107       /* we still have a ref to the pending call in this case, we unref
03108        * after unlocking, below
03109        */
03110     }
03111 
03112   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03113 
03114   /* this calls out to user code */
03115   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03116 
03117   if (pending_return == NULL)
03118     dbus_pending_call_unref (pending);
03119   
03120   return TRUE;
03121 
03122  error:
03123   CONNECTION_UNLOCK (connection);
03124  error_unlocked:
03125   dbus_pending_call_unref (pending);
03126   return FALSE;
03127 }
03128 
03159 DBusMessage*
03160 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03161                                            DBusMessage        *message,
03162                                            int                 timeout_milliseconds,
03163                                            DBusError          *error)
03164 {
03165   DBusMessage *reply;
03166   DBusPendingCall *pending;
03167   
03168   _dbus_return_val_if_fail (connection != NULL, NULL);
03169   _dbus_return_val_if_fail (message != NULL, NULL);
03170   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03171   _dbus_return_val_if_error_is_set (error, NULL);
03172   
03173   if (!dbus_connection_send_with_reply (connection, message,
03174                                         &pending, timeout_milliseconds))
03175     {
03176       _DBUS_SET_OOM (error);
03177       return NULL;
03178     }
03179 
03180   if (pending == NULL)
03181     {
03182       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03183       return NULL;
03184     }
03185   
03186   dbus_pending_call_block (pending);
03187 
03188   reply = dbus_pending_call_steal_reply (pending);
03189   dbus_pending_call_unref (pending);
03190 
03191   /* call_complete_and_unlock() called from pending_call_block() should
03192    * always fill this in.
03193    */
03194   _dbus_assert (reply != NULL);
03195   
03196    if (dbus_set_error_from_message (error, reply))
03197     {
03198       dbus_message_unref (reply);
03199       return NULL;
03200     }
03201   else
03202     return reply;
03203 }
03204 
03213 DBusDispatchStatus
03214 _dbus_connection_flush_unlocked (DBusConnection *connection)
03215 {
03216   /* We have to specify DBUS_ITERATION_DO_READING here because
03217    * otherwise we could have two apps deadlock if they are both doing
03218    * a flush(), and the kernel buffers fill up. This could change the
03219    * dispatch status.
03220    */
03221   DBusDispatchStatus status;
03222 
03223   HAVE_LOCK_CHECK (connection);
03224   
03225   while (connection->n_outgoing > 0 &&
03226          _dbus_connection_get_is_connected_unlocked (connection))
03227     {
03228       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03229       HAVE_LOCK_CHECK (connection);
03230       _dbus_connection_do_iteration_unlocked (connection,
03231                                               DBUS_ITERATION_DO_READING |
03232                                               DBUS_ITERATION_DO_WRITING |
03233                                               DBUS_ITERATION_BLOCK,
03234                                               -1);
03235     }
03236 
03237   HAVE_LOCK_CHECK (connection);
03238   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03239   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03240 
03241   HAVE_LOCK_CHECK (connection);
03242   return status;
03243 }
03244 
03250 void
03251 dbus_connection_flush (DBusConnection *connection)
03252 {
03253   /* We have to specify DBUS_ITERATION_DO_READING here because
03254    * otherwise we could have two apps deadlock if they are both doing
03255    * a flush(), and the kernel buffers fill up. This could change the
03256    * dispatch status.
03257    */
03258   DBusDispatchStatus status;
03259 
03260   _dbus_return_if_fail (connection != NULL);
03261   
03262   CONNECTION_LOCK (connection);
03263 
03264   status = _dbus_connection_flush_unlocked (connection);
03265   
03266   HAVE_LOCK_CHECK (connection);
03267   /* Unlocks and calls out to user code */
03268   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03269 
03270   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03271 }
03272 
03283 static dbus_bool_t
03284 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03285                                      int             timeout_milliseconds, 
03286                                      dbus_bool_t     dispatch)
03287 {
03288   DBusDispatchStatus dstatus;
03289   dbus_bool_t no_progress_possible;
03290   
03291   dstatus = dbus_connection_get_dispatch_status (connection);
03292 
03293   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03294     {
03295       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03296       dbus_connection_dispatch (connection);
03297       CONNECTION_LOCK (connection);
03298     }
03299   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03300     {
03301       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03302       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03303       CONNECTION_LOCK (connection);
03304     }
03305   else
03306     {
03307       CONNECTION_LOCK (connection);
03308       if (_dbus_connection_get_is_connected_unlocked (connection))
03309         {
03310           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03311           _dbus_connection_do_iteration_unlocked (connection,
03312                                                   DBUS_ITERATION_DO_READING |
03313                                                   DBUS_ITERATION_DO_WRITING |
03314                                                   DBUS_ITERATION_BLOCK,
03315                                                   timeout_milliseconds);
03316         }
03317     }
03318   
03319   HAVE_LOCK_CHECK (connection);
03320   /* If we can dispatch, we can make progress until the Disconnected message
03321    * has been processed; if we can only read/write, we can make progress
03322    * as long as the transport is open.
03323    */
03324   if (dispatch)
03325     no_progress_possible = connection->n_incoming == 0 &&
03326       connection->disconnect_message_link == NULL;
03327   else
03328     no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03329   CONNECTION_UNLOCK (connection);
03330   return !no_progress_possible; /* TRUE if we can make more progress */
03331 }
03332 
03333 
03368 dbus_bool_t
03369 dbus_connection_read_write_dispatch (DBusConnection *connection,
03370                                      int             timeout_milliseconds)
03371 {
03372   _dbus_return_val_if_fail (connection != NULL, FALSE);
03373   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03374    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03375 }
03376 
03400 dbus_bool_t 
03401 dbus_connection_read_write (DBusConnection *connection, 
03402                             int             timeout_milliseconds) 
03403 { 
03404   _dbus_return_val_if_fail (connection != NULL, FALSE);
03405   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03406    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03407 }
03408 
03409 /* We need to call this anytime we pop the head of the queue, and then
03410  * update_dispatch_status_and_unlock needs to be called afterward
03411  * which will "process" the disconnected message and set
03412  * disconnected_message_processed.
03413  */
03414 static void
03415 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03416                                              DBusMessage    *head_of_queue)
03417 {
03418   HAVE_LOCK_CHECK (connection);
03419 
03420   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03421   if (connection->disconnect_message_link == NULL &&
03422       dbus_message_is_signal (head_of_queue,
03423                               DBUS_INTERFACE_LOCAL,
03424                               "Disconnected"))
03425     {
03426       connection->disconnected_message_arrived = TRUE;
03427     }
03428 }
03429 
03449 DBusMessage*
03450 dbus_connection_borrow_message (DBusConnection *connection)
03451 {
03452   DBusDispatchStatus status;
03453   DBusMessage *message;
03454 
03455   _dbus_return_val_if_fail (connection != NULL, NULL);
03456 
03457   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03458   
03459   /* this is called for the side effect that it queues
03460    * up any messages from the transport
03461    */
03462   status = dbus_connection_get_dispatch_status (connection);
03463   if (status != DBUS_DISPATCH_DATA_REMAINS)
03464     return NULL;
03465   
03466   CONNECTION_LOCK (connection);
03467 
03468   _dbus_connection_acquire_dispatch (connection);
03469 
03470   /* While a message is outstanding, the dispatch lock is held */
03471   _dbus_assert (connection->message_borrowed == NULL);
03472 
03473   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03474   
03475   message = connection->message_borrowed;
03476 
03477   check_disconnected_message_arrived_unlocked (connection, message);
03478   
03479   /* Note that we KEEP the dispatch lock until the message is returned */
03480   if (message == NULL)
03481     _dbus_connection_release_dispatch (connection);
03482 
03483   CONNECTION_UNLOCK (connection);
03484 
03485   /* We don't update dispatch status until it's returned or stolen */
03486   
03487   return message;
03488 }
03489 
03498 void
03499 dbus_connection_return_message (DBusConnection *connection,
03500                                 DBusMessage    *message)
03501 {
03502   DBusDispatchStatus status;
03503   
03504   _dbus_return_if_fail (connection != NULL);
03505   _dbus_return_if_fail (message != NULL);
03506   _dbus_return_if_fail (message == connection->message_borrowed);
03507   _dbus_return_if_fail (connection->dispatch_acquired);
03508   
03509   CONNECTION_LOCK (connection);
03510   
03511   _dbus_assert (message == connection->message_borrowed);
03512   
03513   connection->message_borrowed = NULL;
03514 
03515   _dbus_connection_release_dispatch (connection); 
03516 
03517   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03518   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03519 }
03520 
03530 void
03531 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03532                                         DBusMessage    *message)
03533 {
03534   DBusMessage *pop_message;
03535   DBusDispatchStatus status;
03536 
03537   _dbus_return_if_fail (connection != NULL);
03538   _dbus_return_if_fail (message != NULL);
03539   _dbus_return_if_fail (message == connection->message_borrowed);
03540   _dbus_return_if_fail (connection->dispatch_acquired);
03541   
03542   CONNECTION_LOCK (connection);
03543  
03544   _dbus_assert (message == connection->message_borrowed);
03545 
03546   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03547   _dbus_assert (message == pop_message);
03548   
03549   connection->n_incoming -= 1;
03550  
03551   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03552                  message, connection->n_incoming);
03553  
03554   connection->message_borrowed = NULL;
03555 
03556   _dbus_connection_release_dispatch (connection);
03557 
03558   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03559   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03560 }
03561 
03562 /* See dbus_connection_pop_message, but requires the caller to own
03563  * the lock before calling. May drop the lock while running.
03564  */
03565 static DBusList*
03566 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03567 {
03568   HAVE_LOCK_CHECK (connection);
03569   
03570   _dbus_assert (connection->message_borrowed == NULL);
03571   
03572   if (connection->n_incoming > 0)
03573     {
03574       DBusList *link;
03575 
03576       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03577       connection->n_incoming -= 1;
03578 
03579       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03580                      link->data,
03581                      dbus_message_get_type (link->data),
03582                      dbus_message_get_path (link->data) ?
03583                      dbus_message_get_path (link->data) :
03584                      "no path",
03585                      dbus_message_get_interface (link->data) ?
03586                      dbus_message_get_interface (link->data) :
03587                      "no interface",
03588                      dbus_message_get_member (link->data) ?
03589                      dbus_message_get_member (link->data) :
03590                      "no member",
03591                      dbus_message_get_signature (link->data),
03592                      connection, connection->n_incoming);
03593 
03594       check_disconnected_message_arrived_unlocked (connection, link->data);
03595       
03596       return link;
03597     }
03598   else
03599     return NULL;
03600 }
03601 
03602 /* See dbus_connection_pop_message, but requires the caller to own
03603  * the lock before calling. May drop the lock while running.
03604  */
03605 static DBusMessage*
03606 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03607 {
03608   DBusList *link;
03609 
03610   HAVE_LOCK_CHECK (connection);
03611   
03612   link = _dbus_connection_pop_message_link_unlocked (connection);
03613 
03614   if (link != NULL)
03615     {
03616       DBusMessage *message;
03617       
03618       message = link->data;
03619       
03620       _dbus_list_free_link (link);
03621       
03622       return message;
03623     }
03624   else
03625     return NULL;
03626 }
03627 
03628 static void
03629 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03630                                                 DBusList       *message_link)
03631 {
03632   HAVE_LOCK_CHECK (connection);
03633   
03634   _dbus_assert (message_link != NULL);
03635   /* You can't borrow a message while a link is outstanding */
03636   _dbus_assert (connection->message_borrowed == NULL);
03637   /* We had to have the dispatch lock across the pop/putback */
03638   _dbus_assert (connection->dispatch_acquired);
03639 
03640   _dbus_list_prepend_link (&connection->incoming_messages,
03641                            message_link);
03642   connection->n_incoming += 1;
03643 
03644   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03645                  message_link->data,
03646                  dbus_message_get_type (message_link->data),
03647                  dbus_message_get_interface (message_link->data) ?
03648                  dbus_message_get_interface (message_link->data) :
03649                  "no interface",
03650                  dbus_message_get_member (message_link->data) ?
03651                  dbus_message_get_member (message_link->data) :
03652                  "no member",
03653                  dbus_message_get_signature (message_link->data),
03654                  connection, connection->n_incoming);
03655 }
03656 
03676 DBusMessage*
03677 dbus_connection_pop_message (DBusConnection *connection)
03678 {
03679   DBusMessage *message;
03680   DBusDispatchStatus status;
03681 
03682   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03683   
03684   /* this is called for the side effect that it queues
03685    * up any messages from the transport
03686    */
03687   status = dbus_connection_get_dispatch_status (connection);
03688   if (status != DBUS_DISPATCH_DATA_REMAINS)
03689     return NULL;
03690   
03691   CONNECTION_LOCK (connection);
03692   _dbus_connection_acquire_dispatch (connection);
03693   HAVE_LOCK_CHECK (connection);
03694   
03695   message = _dbus_connection_pop_message_unlocked (connection);
03696 
03697   _dbus_verbose ("Returning popped message %p\n", message);    
03698 
03699   _dbus_connection_release_dispatch (connection);
03700 
03701   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03702   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03703   
03704   return message;
03705 }
03706 
03714 static void
03715 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03716 {
03717   HAVE_LOCK_CHECK (connection);
03718 
03719   _dbus_connection_ref_unlocked (connection);
03720   CONNECTION_UNLOCK (connection);
03721   
03722   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03723   _dbus_mutex_lock (connection->dispatch_mutex);
03724 
03725   while (connection->dispatch_acquired)
03726     {
03727       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03728       _dbus_condvar_wait (connection->dispatch_cond, 
03729                           connection->dispatch_mutex);
03730     }
03731   
03732   _dbus_assert (!connection->dispatch_acquired);
03733 
03734   connection->dispatch_acquired = TRUE;
03735 
03736   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03737   _dbus_mutex_unlock (connection->dispatch_mutex);
03738   
03739   CONNECTION_LOCK (connection);
03740   _dbus_connection_unref_unlocked (connection);
03741 }
03742 
03750 static void
03751 _dbus_connection_release_dispatch (DBusConnection *connection)
03752 {
03753   HAVE_LOCK_CHECK (connection);
03754   
03755   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03756   _dbus_mutex_lock (connection->dispatch_mutex);
03757   
03758   _dbus_assert (connection->dispatch_acquired);
03759 
03760   connection->dispatch_acquired = FALSE;
03761   _dbus_condvar_wake_one (connection->dispatch_cond);
03762 
03763   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03764   _dbus_mutex_unlock (connection->dispatch_mutex);
03765 }
03766 
03767 static void
03768 _dbus_connection_failed_pop (DBusConnection *connection,
03769                              DBusList       *message_link)
03770 {
03771   _dbus_list_prepend_link (&connection->incoming_messages,
03772                            message_link);
03773   connection->n_incoming += 1;
03774 }
03775 
03776 /* Note this may be called multiple times since we don't track whether we already did it */
03777 static void
03778 notify_disconnected_unlocked (DBusConnection *connection)
03779 {
03780   HAVE_LOCK_CHECK (connection);
03781 
03782   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
03783    * connection from dbus_bus_get(). We make the same guarantee for
03784    * dbus_connection_open() but in a different way since we don't want to
03785    * unref right here; we instead check for connectedness before returning
03786    * the connection from the hash.
03787    */
03788   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03789 
03790   /* Dump the outgoing queue, we aren't going to be able to
03791    * send it now, and we'd like accessors like
03792    * dbus_connection_get_outgoing_size() to be accurate.
03793    */
03794   if (connection->n_outgoing > 0)
03795     {
03796       DBusList *link;
03797       
03798       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03799                      connection->n_outgoing);
03800       
03801       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03802         {
03803           _dbus_connection_message_sent (connection, link->data);
03804         }
03805     } 
03806 }
03807 
03808 /* Note this may be called multiple times since we don't track whether we already did it */
03809 static DBusDispatchStatus
03810 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03811 {
03812   HAVE_LOCK_CHECK (connection);
03813   
03814   if (connection->disconnect_message_link != NULL)
03815     {
03816       _dbus_verbose ("Sending disconnect message from %s\n",
03817                      _DBUS_FUNCTION_NAME);
03818       
03819       /* If we have pending calls, queue their timeouts - we want the Disconnected
03820        * to be the last message, after these timeouts.
03821        */
03822       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03823       
03824       /* We haven't sent the disconnect message already,
03825        * and all real messages have been queued up.
03826        */
03827       _dbus_connection_queue_synthesized_message_link (connection,
03828                                                        connection->disconnect_message_link);
03829       connection->disconnect_message_link = NULL;
03830 
03831       return DBUS_DISPATCH_DATA_REMAINS;
03832     }
03833 
03834   return DBUS_DISPATCH_COMPLETE;
03835 }
03836 
03837 static DBusDispatchStatus
03838 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03839 {
03840   HAVE_LOCK_CHECK (connection);
03841   
03842   if (connection->n_incoming > 0)
03843     return DBUS_DISPATCH_DATA_REMAINS;
03844   else if (!_dbus_transport_queue_messages (connection->transport))
03845     return DBUS_DISPATCH_NEED_MEMORY;
03846   else
03847     {
03848       DBusDispatchStatus status;
03849       dbus_bool_t is_connected;
03850       
03851       status = _dbus_transport_get_dispatch_status (connection->transport);
03852       is_connected = _dbus_transport_get_is_connected (connection->transport);
03853 
03854       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03855                      DISPATCH_STATUS_NAME (status), is_connected);
03856       
03857       if (!is_connected)
03858         {
03859           /* It's possible this would be better done by having an explicit
03860            * notification from _dbus_transport_disconnect() that would
03861            * synchronously do this, instead of waiting for the next dispatch
03862            * status check. However, probably not good to change until it causes
03863            * a problem.
03864            */
03865           notify_disconnected_unlocked (connection);
03866 
03867           /* I'm not sure this is needed; the idea is that we want to
03868            * queue the Disconnected only after we've read all the
03869            * messages, but if we're disconnected maybe we are guaranteed
03870            * to have read them all ?
03871            */
03872           if (status == DBUS_DISPATCH_COMPLETE)
03873             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03874         }
03875       
03876       if (status != DBUS_DISPATCH_COMPLETE)
03877         return status;
03878       else if (connection->n_incoming > 0)
03879         return DBUS_DISPATCH_DATA_REMAINS;
03880       else
03881         return DBUS_DISPATCH_COMPLETE;
03882     }
03883 }
03884 
03885 static void
03886 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03887                                                     DBusDispatchStatus new_status)
03888 {
03889   dbus_bool_t changed;
03890   DBusDispatchStatusFunction function;
03891   void *data;
03892 
03893   HAVE_LOCK_CHECK (connection);
03894 
03895   _dbus_connection_ref_unlocked (connection);
03896 
03897   changed = new_status != connection->last_dispatch_status;
03898 
03899   connection->last_dispatch_status = new_status;
03900 
03901   function = connection->dispatch_status_function;
03902   data = connection->dispatch_status_data;
03903 
03904   if (connection->disconnected_message_arrived &&
03905       !connection->disconnected_message_processed)
03906     {
03907       connection->disconnected_message_processed = TRUE;
03908       
03909       /* this does an unref, but we have a ref
03910        * so we should not run the finalizer here
03911        * inside the lock.
03912        */
03913       connection_forget_shared_unlocked (connection);
03914 
03915       if (connection->exit_on_disconnect)
03916         {
03917           CONNECTION_UNLOCK (connection);            
03918           
03919           _dbus_verbose ("Exiting on Disconnected signal\n");
03920           _dbus_exit (1);
03921           _dbus_assert_not_reached ("Call to exit() returned");
03922         }
03923     }
03924   
03925   /* We drop the lock */
03926   CONNECTION_UNLOCK (connection);
03927   
03928   if (changed && function)
03929     {
03930       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03931                      connection, new_status,
03932                      DISPATCH_STATUS_NAME (new_status));
03933       (* function) (connection, new_status, data);      
03934     }
03935   
03936   dbus_connection_unref (connection);
03937 }
03938 
03964 DBusDispatchStatus
03965 dbus_connection_get_dispatch_status (DBusConnection *connection)
03966 {
03967   DBusDispatchStatus status;
03968 
03969   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03970 
03971   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03972   
03973   CONNECTION_LOCK (connection);
03974 
03975   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03976   
03977   CONNECTION_UNLOCK (connection);
03978 
03979   return status;
03980 }
03981 
03985 static DBusHandlerResult
03986 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03987                                                  DBusMessage    *message)
03988 {
03989   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
03990     {
03991       /* This means we're letting the bus route this message */
03992       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03993     }
03994   else if (dbus_message_is_method_call (message,
03995                                         DBUS_INTERFACE_PEER,
03996                                         "Ping"))
03997     {
03998       DBusMessage *ret;
03999       dbus_bool_t sent;
04000       
04001       ret = dbus_message_new_method_return (message);
04002       if (ret == NULL)
04003         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04004      
04005       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04006 
04007       dbus_message_unref (ret);
04008 
04009       if (!sent)
04010         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04011       
04012       return DBUS_HANDLER_RESULT_HANDLED;
04013     }
04014   else if (dbus_message_is_method_call (message,
04015                                         DBUS_INTERFACE_PEER,
04016                                         "GetMachineId"))
04017     {
04018       DBusMessage *ret;
04019       dbus_bool_t sent;
04020       DBusString uuid;
04021       
04022       ret = dbus_message_new_method_return (message);
04023       if (ret == NULL)
04024         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04025 
04026       sent = FALSE;
04027       _dbus_string_init (&uuid);
04028       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04029         {
04030           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04031           if (dbus_message_append_args (ret,
04032                                         DBUS_TYPE_STRING, &v_STRING,
04033                                         DBUS_TYPE_INVALID))
04034             {
04035               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04036             }
04037         }
04038       _dbus_string_free (&uuid);
04039       
04040       dbus_message_unref (ret);
04041 
04042       if (!sent)
04043         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04044       
04045       return DBUS_HANDLER_RESULT_HANDLED;
04046     }
04047   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04048     {
04049       /* We need to bounce anything else with this interface, otherwise apps
04050        * could start extending the interface and when we added extensions
04051        * here to DBusConnection we'd break those apps.
04052        */
04053       
04054       DBusMessage *ret;
04055       dbus_bool_t sent;
04056       
04057       ret = dbus_message_new_error (message,
04058                                     DBUS_ERROR_UNKNOWN_METHOD,
04059                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04060       if (ret == NULL)
04061         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04062       
04063       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04064       
04065       dbus_message_unref (ret);
04066       
04067       if (!sent)
04068         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04069       
04070       return DBUS_HANDLER_RESULT_HANDLED;
04071     }
04072   else
04073     {
04074       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04075     }
04076 }
04077 
04084 static DBusHandlerResult
04085 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04086                                                            DBusMessage    *message)
04087 {
04088   /* We just run one filter for now but have the option to run more
04089      if the spec calls for it in the future */
04090 
04091   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04092 }
04093 
04136 DBusDispatchStatus
04137 dbus_connection_dispatch (DBusConnection *connection)
04138 {
04139   DBusMessage *message;
04140   DBusList *link, *filter_list_copy, *message_link;
04141   DBusHandlerResult result;
04142   DBusPendingCall *pending;
04143   dbus_int32_t reply_serial;
04144   DBusDispatchStatus status;
04145 
04146   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04147 
04148   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04149   
04150   CONNECTION_LOCK (connection);
04151   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04152   if (status != DBUS_DISPATCH_DATA_REMAINS)
04153     {
04154       /* unlocks and calls out to user code */
04155       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04156       return status;
04157     }
04158   
04159   /* We need to ref the connection since the callback could potentially
04160    * drop the last ref to it
04161    */
04162   _dbus_connection_ref_unlocked (connection);
04163 
04164   _dbus_connection_acquire_dispatch (connection);
04165   HAVE_LOCK_CHECK (connection);
04166 
04167   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04168   if (message_link == NULL)
04169     {
04170       /* another thread dispatched our stuff */
04171 
04172       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04173       
04174       _dbus_connection_release_dispatch (connection);
04175 
04176       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04177 
04178       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04179       
04180       dbus_connection_unref (connection);
04181       
04182       return status;
04183     }
04184 
04185   message = message_link->data;
04186 
04187   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04188                  message,
04189                  dbus_message_get_type (message),
04190                  dbus_message_get_interface (message) ?
04191                  dbus_message_get_interface (message) :
04192                  "no interface",
04193                  dbus_message_get_member (message) ?
04194                  dbus_message_get_member (message) :
04195                  "no member",
04196                  dbus_message_get_signature (message));
04197 
04198   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04199   
04200   /* Pending call handling must be first, because if you do
04201    * dbus_connection_send_with_reply_and_block() or
04202    * dbus_pending_call_block() then no handlers/filters will be run on
04203    * the reply. We want consistent semantics in the case where we
04204    * dbus_connection_dispatch() the reply.
04205    */
04206   
04207   reply_serial = dbus_message_get_reply_serial (message);
04208   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04209                                          reply_serial);
04210   if (pending)
04211     {
04212       _dbus_verbose ("Dispatching a pending reply\n");
04213       complete_pending_call_and_unlock (connection, pending, message);
04214       pending = NULL; /* it's probably unref'd */
04215       
04216       CONNECTION_LOCK (connection);
04217       _dbus_verbose ("pending call completed in dispatch\n");
04218       result = DBUS_HANDLER_RESULT_HANDLED;
04219       goto out;
04220     }
04221 
04222   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04223   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04224     goto out;
04225  
04226   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04227     {
04228       _dbus_connection_release_dispatch (connection);
04229       HAVE_LOCK_CHECK (connection);
04230       
04231       _dbus_connection_failed_pop (connection, message_link);
04232 
04233       /* unlocks and calls user code */
04234       _dbus_connection_update_dispatch_status_and_unlock (connection,
04235                                                           DBUS_DISPATCH_NEED_MEMORY);
04236 
04237       if (pending)
04238         dbus_pending_call_unref (pending);
04239       dbus_connection_unref (connection);
04240       
04241       return DBUS_DISPATCH_NEED_MEMORY;
04242     }
04243   
04244   _dbus_list_foreach (&filter_list_copy,
04245                       (DBusForeachFunction)_dbus_message_filter_ref,
04246                       NULL);
04247 
04248   /* We're still protected from dispatch() reentrancy here
04249    * since we acquired the dispatcher
04250    */
04251   CONNECTION_UNLOCK (connection);
04252   
04253   link = _dbus_list_get_first_link (&filter_list_copy);
04254   while (link != NULL)
04255     {
04256       DBusMessageFilter *filter = link->data;
04257       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04258 
04259       if (filter->function == NULL)
04260         {
04261           _dbus_verbose ("  filter was removed in a callback function\n");
04262           link = next;
04263           continue;
04264         }
04265 
04266       _dbus_verbose ("  running filter on message %p\n", message);
04267       result = (* filter->function) (connection, message, filter->user_data);
04268 
04269       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04270         break;
04271 
04272       link = next;
04273     }
04274 
04275   _dbus_list_foreach (&filter_list_copy,
04276                       (DBusForeachFunction)_dbus_message_filter_unref,
04277                       NULL);
04278   _dbus_list_clear (&filter_list_copy);
04279   
04280   CONNECTION_LOCK (connection);
04281 
04282   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04283     {
04284       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04285       goto out;
04286     }
04287   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04288     {
04289       _dbus_verbose ("filter handled message in dispatch\n");
04290       goto out;
04291     }
04292 
04293   /* We're still protected from dispatch() reentrancy here
04294    * since we acquired the dispatcher
04295    */
04296   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
04297                  message,
04298                  dbus_message_get_type (message),
04299                  dbus_message_get_interface (message) ?
04300                  dbus_message_get_interface (message) :
04301                  "no interface",
04302                  dbus_message_get_member (message) ?
04303                  dbus_message_get_member (message) :
04304                  "no member",
04305                  dbus_message_get_signature (message));
04306 
04307   HAVE_LOCK_CHECK (connection);
04308   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04309                                                   message);
04310   
04311   CONNECTION_LOCK (connection);
04312 
04313   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04314     {
04315       _dbus_verbose ("object tree handled message in dispatch\n");
04316       goto out;
04317     }
04318 
04319   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04320     {
04321       DBusMessage *reply;
04322       DBusString str;
04323       DBusPreallocatedSend *preallocated;
04324 
04325       _dbus_verbose ("  sending error %s\n",
04326                      DBUS_ERROR_UNKNOWN_METHOD);
04327       
04328       if (!_dbus_string_init (&str))
04329         {
04330           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04331           _dbus_verbose ("no memory for error string in dispatch\n");
04332           goto out;
04333         }
04334               
04335       if (!_dbus_string_append_printf (&str,
04336                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04337                                        dbus_message_get_member (message),
04338                                        dbus_message_get_signature (message),
04339                                        dbus_message_get_interface (message)))
04340         {
04341           _dbus_string_free (&str);
04342           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04343           _dbus_verbose ("no memory for error string in dispatch\n");
04344           goto out;
04345         }
04346       
04347       reply = dbus_message_new_error (message,
04348                                       DBUS_ERROR_UNKNOWN_METHOD,
04349                                       _dbus_string_get_const_data (&str));
04350       _dbus_string_free (&str);
04351 
04352       if (reply == NULL)
04353         {
04354           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04355           _dbus_verbose ("no memory for error reply in dispatch\n");
04356           goto out;
04357         }
04358       
04359       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04360 
04361       if (preallocated == NULL)
04362         {
04363           dbus_message_unref (reply);
04364           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04365           _dbus_verbose ("no memory for error send in dispatch\n");
04366           goto out;
04367         }
04368 
04369       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04370                                                              reply, NULL);
04371 
04372       dbus_message_unref (reply);
04373       
04374       result = DBUS_HANDLER_RESULT_HANDLED;
04375     }
04376   
04377   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04378                  dbus_message_get_type (message),
04379                  dbus_message_get_interface (message) ?
04380                  dbus_message_get_interface (message) :
04381                  "no interface",
04382                  dbus_message_get_member (message) ?
04383                  dbus_message_get_member (message) :
04384                  "no member",
04385                  dbus_message_get_signature (message),
04386                  connection);
04387   
04388  out:
04389   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04390     {
04391       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04392       
04393       /* Put message back, and we'll start over.
04394        * Yes this means handlers must be idempotent if they
04395        * don't return HANDLED; c'est la vie.
04396        */
04397       _dbus_connection_putback_message_link_unlocked (connection,
04398                                                       message_link);
04399     }
04400   else
04401     {
04402       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04403       
04404       _dbus_list_free_link (message_link);
04405       dbus_message_unref (message); /* don't want the message to count in max message limits
04406                                      * in computing dispatch status below
04407                                      */
04408     }
04409   
04410   _dbus_connection_release_dispatch (connection);
04411   HAVE_LOCK_CHECK (connection);
04412 
04413   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04414   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04415 
04416   /* unlocks and calls user code */
04417   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04418   
04419   dbus_connection_unref (connection);
04420   
04421   return status;
04422 }
04423 
04482 dbus_bool_t
04483 dbus_connection_set_watch_functions (DBusConnection              *connection,
04484                                      DBusAddWatchFunction         add_function,
04485                                      DBusRemoveWatchFunction      remove_function,
04486                                      DBusWatchToggledFunction     toggled_function,
04487                                      void                        *data,
04488                                      DBusFreeFunction             free_data_function)
04489 {
04490   dbus_bool_t retval;
04491   DBusWatchList *watches;
04492 
04493   _dbus_return_val_if_fail (connection != NULL, FALSE);
04494   
04495   CONNECTION_LOCK (connection);
04496 
04497 #ifndef DBUS_DISABLE_CHECKS
04498   if (connection->watches == NULL)
04499     {
04500       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04501                                _DBUS_FUNCTION_NAME);
04502       return FALSE;
04503     }
04504 #endif
04505   
04506   /* ref connection for slightly better reentrancy */
04507   _dbus_connection_ref_unlocked (connection);
04508 
04509   /* This can call back into user code, and we need to drop the
04510    * connection lock when it does. This is kind of a lame
04511    * way to do it.
04512    */
04513   watches = connection->watches;
04514   connection->watches = NULL;
04515   CONNECTION_UNLOCK (connection);
04516 
04517   retval = _dbus_watch_list_set_functions (watches,
04518                                            add_function, remove_function,
04519                                            toggled_function,
04520                                            data, free_data_function);
04521   CONNECTION_LOCK (connection);
04522   connection->watches = watches;
04523   
04524   CONNECTION_UNLOCK (connection);
04525   /* drop our paranoid refcount */
04526   dbus_connection_unref (connection);
04527   
04528   return retval;
04529 }
04530 
04564 dbus_bool_t
04565 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04566                                          DBusAddTimeoutFunction     add_function,
04567                                          DBusRemoveTimeoutFunction  remove_function,
04568                                          DBusTimeoutToggledFunction toggled_function,
04569                                          void                      *data,
04570                                          DBusFreeFunction           free_data_function)
04571 {
04572   dbus_bool_t retval;
04573   DBusTimeoutList *timeouts;
04574 
04575   _dbus_return_val_if_fail (connection != NULL, FALSE);
04576   
04577   CONNECTION_LOCK (connection);
04578 
04579 #ifndef DBUS_DISABLE_CHECKS
04580   if (connection->timeouts == NULL)
04581     {
04582       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04583                                _DBUS_FUNCTION_NAME);
04584       return FALSE;
04585     }
04586 #endif
04587   
04588   /* ref connection for slightly better reentrancy */
04589   _dbus_connection_ref_unlocked (connection);
04590 
04591   timeouts = connection->timeouts;
04592   connection->timeouts = NULL;
04593   CONNECTION_UNLOCK (connection);
04594   
04595   retval = _dbus_timeout_list_set_functions (timeouts,
04596                                              add_function, remove_function,
04597                                              toggled_function,
04598                                              data, free_data_function);
04599   CONNECTION_LOCK (connection);
04600   connection->timeouts = timeouts;
04601   
04602   CONNECTION_UNLOCK (connection);
04603   /* drop our paranoid refcount */
04604   dbus_connection_unref (connection);
04605 
04606   return retval;
04607 }
04608 
04623 void
04624 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04625                                           DBusWakeupMainFunction     wakeup_main_function,
04626                                           void                      *data,
04627                                           DBusFreeFunction           free_data_function)
04628 {
04629   void *old_data;
04630   DBusFreeFunction old_free_data;
04631 
04632   _dbus_return_if_fail (connection != NULL);
04633   
04634   CONNECTION_LOCK (connection);
04635   old_data = connection->wakeup_main_data;
04636   old_free_data = connection->free_wakeup_main_data;
04637 
04638   connection->wakeup_main_function = wakeup_main_function;
04639   connection->wakeup_main_data = data;
04640   connection->free_wakeup_main_data = free_data_function;
04641   
04642   CONNECTION_UNLOCK (connection);
04643 
04644   /* Callback outside the lock */
04645   if (old_free_data)
04646     (*old_free_data) (old_data);
04647 }
04648 
04669 void
04670 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04671                                               DBusDispatchStatusFunction  function,
04672                                               void                       *data,
04673                                               DBusFreeFunction            free_data_function)
04674 {
04675   void *old_data;
04676   DBusFreeFunction old_free_data;
04677 
04678   _dbus_return_if_fail (connection != NULL);
04679   
04680   CONNECTION_LOCK (connection);
04681   old_data = connection->dispatch_status_data;
04682   old_free_data = connection->free_dispatch_status_data;
04683 
04684   connection->dispatch_status_function = function;
04685   connection->dispatch_status_data = data;
04686   connection->free_dispatch_status_data = free_data_function;
04687   
04688   CONNECTION_UNLOCK (connection);
04689 
04690   /* Callback outside the lock */
04691   if (old_free_data)
04692     (*old_free_data) (old_data);
04693 }
04694 
04714 dbus_bool_t
04715 dbus_connection_get_unix_fd (DBusConnection *connection,
04716                              int            *fd)
04717 {
04718   _dbus_return_val_if_fail (connection != NULL, FALSE);
04719   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04720 
04721 #ifdef DBUS_WIN
04722   /* FIXME do this on a lower level */
04723   return FALSE;
04724 #endif
04725   
04726   return dbus_connection_get_socket(connection, fd);
04727 }
04728 
04744 dbus_bool_t
04745 dbus_connection_get_socket(DBusConnection              *connection,
04746                            int                         *fd)
04747 {
04748   dbus_bool_t retval;
04749 
04750   _dbus_return_val_if_fail (connection != NULL, FALSE);
04751   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04752   
04753   CONNECTION_LOCK (connection);
04754   
04755   retval = _dbus_transport_get_socket_fd (connection->transport,
04756                                           fd);
04757 
04758   CONNECTION_UNLOCK (connection);
04759 
04760   return retval;
04761 }
04762 
04763 
04784 dbus_bool_t
04785 dbus_connection_get_unix_user (DBusConnection *connection,
04786                                unsigned long  *uid)
04787 {
04788   dbus_bool_t result;
04789 
04790   _dbus_return_val_if_fail (connection != NULL, FALSE);
04791   _dbus_return_val_if_fail (uid != NULL, FALSE);
04792 
04793 #ifdef DBUS_WIN
04794   /* FIXME this should be done at a lower level, but it's kind of hard,
04795    * just want to be sure we don't ship with this API returning
04796    * some weird internal fake uid for 1.0
04797    */
04798   return FALSE;
04799 #endif
04800   
04801   CONNECTION_LOCK (connection);
04802 
04803   if (!_dbus_transport_get_is_authenticated (connection->transport))
04804     result = FALSE;
04805   else
04806     result = _dbus_transport_get_unix_user (connection->transport,
04807                                             uid);
04808   CONNECTION_UNLOCK (connection);
04809 
04810   return result;
04811 }
04812 
04823 dbus_bool_t
04824 dbus_connection_get_unix_process_id (DBusConnection *connection,
04825                                      unsigned long  *pid)
04826 {
04827   dbus_bool_t result;
04828 
04829   _dbus_return_val_if_fail (connection != NULL, FALSE);
04830   _dbus_return_val_if_fail (pid != NULL, FALSE);
04831 
04832 #ifdef DBUS_WIN
04833   /* FIXME this should be done at a lower level, but it's kind of hard,
04834    * just want to be sure we don't ship with this API returning
04835    * some weird internal fake uid for 1.0
04836    */
04837   return FALSE;
04838 #endif
04839   
04840   CONNECTION_LOCK (connection);
04841 
04842   if (!_dbus_transport_get_is_authenticated (connection->transport))
04843     result = FALSE;
04844   else
04845     result = _dbus_transport_get_unix_process_id (connection->transport,
04846                                                   pid);
04847   CONNECTION_UNLOCK (connection);
04848 
04849   return result;
04850 }
04851 
04875 void
04876 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04877                                         DBusAllowUnixUserFunction   function,
04878                                         void                       *data,
04879                                         DBusFreeFunction            free_data_function)
04880 {
04881   void *old_data = NULL;
04882   DBusFreeFunction old_free_function = NULL;
04883 
04884   _dbus_return_if_fail (connection != NULL);
04885   
04886   CONNECTION_LOCK (connection);
04887   _dbus_transport_set_unix_user_function (connection->transport,
04888                                           function, data, free_data_function,
04889                                           &old_data, &old_free_function);
04890   CONNECTION_UNLOCK (connection);
04891 
04892   if (old_free_function != NULL)
04893     (* old_free_function) (old_data);    
04894 }
04895 
04914 void
04915 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
04916                                          dbus_bool_t                 value)
04917 {
04918   _dbus_return_if_fail (connection != NULL);
04919   
04920   CONNECTION_LOCK (connection);
04921   connection->route_peer_messages = TRUE;
04922   CONNECTION_UNLOCK (connection);
04923 }
04924 
04946 dbus_bool_t
04947 dbus_connection_add_filter (DBusConnection            *connection,
04948                             DBusHandleMessageFunction  function,
04949                             void                      *user_data,
04950                             DBusFreeFunction           free_data_function)
04951 {
04952   DBusMessageFilter *filter;
04953   
04954   _dbus_return_val_if_fail (connection != NULL, FALSE);
04955   _dbus_return_val_if_fail (function != NULL, FALSE);
04956 
04957   filter = dbus_new0 (DBusMessageFilter, 1);
04958   if (filter == NULL)
04959     return FALSE;
04960 
04961   filter->refcount.value = 1;
04962   
04963   CONNECTION_LOCK (connection);
04964 
04965   if (!_dbus_list_append (&connection->filter_list,
04966                           filter))
04967     {
04968       _dbus_message_filter_unref (filter);
04969       CONNECTION_UNLOCK (connection);
04970       return FALSE;
04971     }
04972 
04973   /* Fill in filter after all memory allocated,
04974    * so we don't run the free_user_data_function
04975    * if the add_filter() fails
04976    */
04977   
04978   filter->function = function;
04979   filter->user_data = user_data;
04980   filter->free_user_data_function = free_data_function;
04981         
04982   CONNECTION_UNLOCK (connection);
04983   return TRUE;
04984 }
04985 
04998 void
04999 dbus_connection_remove_filter (DBusConnection            *connection,
05000                                DBusHandleMessageFunction  function,
05001                                void                      *user_data)
05002 {
05003   DBusList *link;
05004   DBusMessageFilter *filter;
05005   
05006   _dbus_return_if_fail (connection != NULL);
05007   _dbus_return_if_fail (function != NULL);
05008   
05009   CONNECTION_LOCK (connection);
05010 
05011   filter = NULL;
05012   
05013   link = _dbus_list_get_last_link (&connection->filter_list);
05014   while (link != NULL)
05015     {
05016       filter = link->data;
05017 
05018       if (filter->function == function &&
05019           filter->user_data == user_data)
05020         {
05021           _dbus_list_remove_link (&connection->filter_list, link);
05022           filter->function = NULL;
05023           
05024           break;
05025         }
05026         
05027       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05028     }
05029   
05030   CONNECTION_UNLOCK (connection);
05031 
05032 #ifndef DBUS_DISABLE_CHECKS
05033   if (filter == NULL)
05034     {
05035       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05036                                function, user_data);
05037       return;
05038     }
05039 #endif
05040   
05041   /* Call application code */
05042   if (filter->free_user_data_function)
05043     (* filter->free_user_data_function) (filter->user_data);
05044 
05045   filter->free_user_data_function = NULL;
05046   filter->user_data = NULL;
05047   
05048   _dbus_message_filter_unref (filter);
05049 }
05050 
05062 dbus_bool_t
05063 dbus_connection_register_object_path (DBusConnection              *connection,
05064                                       const char                  *path,
05065                                       const DBusObjectPathVTable  *vtable,
05066                                       void                        *user_data)
05067 {
05068   char **decomposed_path;
05069   dbus_bool_t retval;
05070   
05071   _dbus_return_val_if_fail (connection != NULL, FALSE);
05072   _dbus_return_val_if_fail (path != NULL, FALSE);
05073   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05074   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05075 
05076   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05077     return FALSE;
05078 
05079   CONNECTION_LOCK (connection);
05080 
05081   retval = _dbus_object_tree_register (connection->objects,
05082                                        FALSE,
05083                                        (const char **) decomposed_path, vtable,
05084                                        user_data);
05085 
05086   CONNECTION_UNLOCK (connection);
05087 
05088   dbus_free_string_array (decomposed_path);
05089 
05090   return retval;
05091 }
05092 
05105 dbus_bool_t
05106 dbus_connection_register_fallback (DBusConnection              *connection,
05107                                    const char                  *path,
05108                                    const DBusObjectPathVTable  *vtable,
05109                                    void                        *user_data)
05110 {
05111   char **decomposed_path;
05112   dbus_bool_t retval;
05113   
05114   _dbus_return_val_if_fail (connection != NULL, FALSE);
05115   _dbus_return_val_if_fail (path != NULL, FALSE);
05116   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05117   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05118 
05119   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05120     return FALSE;
05121 
05122   CONNECTION_LOCK (connection);
05123 
05124   retval = _dbus_object_tree_register (connection->objects,
05125                                        TRUE,
05126                                        (const char **) decomposed_path, vtable,
05127                                        user_data);
05128 
05129   CONNECTION_UNLOCK (connection);
05130 
05131   dbus_free_string_array (decomposed_path);
05132 
05133   return retval;
05134 }
05135 
05145 dbus_bool_t
05146 dbus_connection_unregister_object_path (DBusConnection              *connection,
05147                                         const char                  *path)
05148 {
05149   char **decomposed_path;
05150 
05151   _dbus_return_val_if_fail (connection != NULL, FALSE);
05152   _dbus_return_val_if_fail (path != NULL, FALSE);
05153   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05154 
05155   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05156       return FALSE;
05157 
05158   CONNECTION_LOCK (connection);
05159 
05160   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05161 
05162   dbus_free_string_array (decomposed_path);
05163 
05164   return TRUE;
05165 }
05166 
05177 dbus_bool_t
05178 dbus_connection_get_object_path_data (DBusConnection *connection,
05179                                       const char     *path,
05180                                       void          **data_p)
05181 {
05182   char **decomposed_path;
05183 
05184   _dbus_return_val_if_fail (connection != NULL, FALSE);
05185   _dbus_return_val_if_fail (path != NULL, FALSE);
05186   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05187 
05188   *data_p = NULL;
05189   
05190   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05191     return FALSE;
05192   
05193   CONNECTION_LOCK (connection);
05194 
05195   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05196 
05197   CONNECTION_UNLOCK (connection);
05198 
05199   dbus_free_string_array (decomposed_path);
05200 
05201   return TRUE;
05202 }
05203 
05214 dbus_bool_t
05215 dbus_connection_list_registered (DBusConnection              *connection,
05216                                  const char                  *parent_path,
05217                                  char                      ***child_entries)
05218 {
05219   char **decomposed_path;
05220   dbus_bool_t retval;
05221   _dbus_return_val_if_fail (connection != NULL, FALSE);
05222   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05223   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05224   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05225 
05226   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05227     return FALSE;
05228 
05229   CONNECTION_LOCK (connection);
05230 
05231   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05232                                                          (const char **) decomposed_path,
05233                                                          child_entries);
05234   dbus_free_string_array (decomposed_path);
05235 
05236   return retval;
05237 }
05238 
05239 static DBusDataSlotAllocator slot_allocator;
05240 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05241 
05256 dbus_bool_t
05257 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05258 {
05259   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05260                                           &_DBUS_LOCK_NAME (connection_slots),
05261                                           slot_p);
05262 }
05263 
05275 void
05276 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05277 {
05278   _dbus_return_if_fail (*slot_p >= 0);
05279   
05280   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05281 }
05282 
05296 dbus_bool_t
05297 dbus_connection_set_data (DBusConnection   *connection,
05298                           dbus_int32_t      slot,
05299                           void             *data,
05300                           DBusFreeFunction  free_data_func)
05301 {
05302   DBusFreeFunction old_free_func;
05303   void *old_data;
05304   dbus_bool_t retval;
05305 
05306   _dbus_return_val_if_fail (connection != NULL, FALSE);
05307   _dbus_return_val_if_fail (slot >= 0, FALSE);
05308   
05309   CONNECTION_LOCK (connection);
05310 
05311   retval = _dbus_data_slot_list_set (&slot_allocator,
05312                                      &connection->slot_list,
05313                                      slot, data, free_data_func,
05314                                      &old_free_func, &old_data);
05315   
05316   CONNECTION_UNLOCK (connection);
05317 
05318   if (retval)
05319     {
05320       /* Do the actual free outside the connection lock */
05321       if (old_free_func)
05322         (* old_free_func) (old_data);
05323     }
05324 
05325   return retval;
05326 }
05327 
05336 void*
05337 dbus_connection_get_data (DBusConnection   *connection,
05338                           dbus_int32_t      slot)
05339 {
05340   void *res;
05341 
05342   _dbus_return_val_if_fail (connection != NULL, NULL);
05343   
05344   CONNECTION_LOCK (connection);
05345 
05346   res = _dbus_data_slot_list_get (&slot_allocator,
05347                                   &connection->slot_list,
05348                                   slot);
05349   
05350   CONNECTION_UNLOCK (connection);
05351 
05352   return res;
05353 }
05354 
05361 void
05362 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05363 {  
05364   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05365 }
05366 
05375 void
05376 dbus_connection_set_max_message_size (DBusConnection *connection,
05377                                       long            size)
05378 {
05379   _dbus_return_if_fail (connection != NULL);
05380   
05381   CONNECTION_LOCK (connection);
05382   _dbus_transport_set_max_message_size (connection->transport,
05383                                         size);
05384   CONNECTION_UNLOCK (connection);
05385 }
05386 
05393 long
05394 dbus_connection_get_max_message_size (DBusConnection *connection)
05395 {
05396   long res;
05397 
05398   _dbus_return_val_if_fail (connection != NULL, 0);
05399   
05400   CONNECTION_LOCK (connection);
05401   res = _dbus_transport_get_max_message_size (connection->transport);
05402   CONNECTION_UNLOCK (connection);
05403   return res;
05404 }
05405 
05431 void
05432 dbus_connection_set_max_received_size (DBusConnection *connection,
05433                                        long            size)
05434 {
05435   _dbus_return_if_fail (connection != NULL);
05436   
05437   CONNECTION_LOCK (connection);
05438   _dbus_transport_set_max_received_size (connection->transport,
05439                                          size);
05440   CONNECTION_UNLOCK (connection);
05441 }
05442 
05449 long
05450 dbus_connection_get_max_received_size (DBusConnection *connection)
05451 {
05452   long res;
05453 
05454   _dbus_return_val_if_fail (connection != NULL, 0);
05455   
05456   CONNECTION_LOCK (connection);
05457   res = _dbus_transport_get_max_received_size (connection->transport);
05458   CONNECTION_UNLOCK (connection);
05459   return res;
05460 }
05461 
05472 long
05473 dbus_connection_get_outgoing_size (DBusConnection *connection)
05474 {
05475   long res;
05476 
05477   _dbus_return_val_if_fail (connection != NULL, 0);
05478   
05479   CONNECTION_LOCK (connection);
05480   res = _dbus_counter_get_value (connection->outgoing_counter);
05481   CONNECTION_UNLOCK (connection);
05482   return res;
05483 }
05484 

Generated on Tue Dec 12 22:54:26 2006 for D-Bus by  doxygen 1.5.1