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 
02833 dbus_bool_t
02834 dbus_connection_get_is_anonymous (DBusConnection *connection)
02835 {
02836   dbus_bool_t res;
02837 
02838   _dbus_return_val_if_fail (connection != NULL, FALSE);
02839   
02840   CONNECTION_LOCK (connection);
02841   res = _dbus_transport_get_is_anonymous (connection->transport);
02842   CONNECTION_UNLOCK (connection);
02843   
02844   return res;
02845 }
02846 
02878 char*
02879 dbus_connection_get_server_id (DBusConnection *connection)
02880 {
02881   char *id;
02882 
02883   _dbus_return_val_if_fail (connection != NULL, FALSE);
02884   
02885   CONNECTION_LOCK (connection);
02886   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02887   CONNECTION_UNLOCK (connection);
02888   
02889   return id;
02890 }
02891 
02905 void
02906 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02907                                         dbus_bool_t     exit_on_disconnect)
02908 {
02909   _dbus_return_if_fail (connection != NULL);
02910 
02911   CONNECTION_LOCK (connection);
02912   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02913   CONNECTION_UNLOCK (connection);
02914 }
02915 
02925 DBusPreallocatedSend*
02926 dbus_connection_preallocate_send (DBusConnection *connection)
02927 {
02928   DBusPreallocatedSend *preallocated;
02929 
02930   _dbus_return_val_if_fail (connection != NULL, NULL);
02931 
02932   CONNECTION_LOCK (connection);
02933   
02934   preallocated =
02935     _dbus_connection_preallocate_send_unlocked (connection);
02936 
02937   CONNECTION_UNLOCK (connection);
02938 
02939   return preallocated;
02940 }
02941 
02951 void
02952 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02953                                         DBusPreallocatedSend *preallocated)
02954 {
02955   _dbus_return_if_fail (connection != NULL);
02956   _dbus_return_if_fail (preallocated != NULL);  
02957   _dbus_return_if_fail (connection == preallocated->connection);
02958 
02959   _dbus_list_free_link (preallocated->queue_link);
02960   _dbus_counter_unref (preallocated->counter_link->data);
02961   _dbus_list_free_link (preallocated->counter_link);
02962   dbus_free (preallocated);
02963 }
02964 
02977 void
02978 dbus_connection_send_preallocated (DBusConnection       *connection,
02979                                    DBusPreallocatedSend *preallocated,
02980                                    DBusMessage          *message,
02981                                    dbus_uint32_t        *client_serial)
02982 {
02983   _dbus_return_if_fail (connection != NULL);
02984   _dbus_return_if_fail (preallocated != NULL);
02985   _dbus_return_if_fail (message != NULL);
02986   _dbus_return_if_fail (preallocated->connection == connection);
02987   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02988                         dbus_message_get_member (message) != NULL);
02989   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02990                         (dbus_message_get_interface (message) != NULL &&
02991                          dbus_message_get_member (message) != NULL));
02992   
02993   CONNECTION_LOCK (connection);
02994   _dbus_connection_send_preallocated_and_unlock (connection,
02995                                                  preallocated,
02996                                                  message, client_serial);
02997 }
02998 
02999 static dbus_bool_t
03000 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03001                                           DBusMessage    *message,
03002                                           dbus_uint32_t  *client_serial)
03003 {
03004   DBusPreallocatedSend *preallocated;
03005 
03006   _dbus_assert (connection != NULL);
03007   _dbus_assert (message != NULL);
03008   
03009   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03010   if (preallocated == NULL)
03011     return FALSE;
03012 
03013   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03014                                                          preallocated,
03015                                                          message,
03016                                                          client_serial);
03017   return TRUE;
03018 }
03019 
03041 dbus_bool_t
03042 dbus_connection_send (DBusConnection *connection,
03043                       DBusMessage    *message,
03044                       dbus_uint32_t  *serial)
03045 {
03046   _dbus_return_val_if_fail (connection != NULL, FALSE);
03047   _dbus_return_val_if_fail (message != NULL, FALSE);
03048 
03049   CONNECTION_LOCK (connection);
03050 
03051   return _dbus_connection_send_and_unlock (connection,
03052                                            message,
03053                                            serial);
03054 }
03055 
03056 static dbus_bool_t
03057 reply_handler_timeout (void *data)
03058 {
03059   DBusConnection *connection;
03060   DBusDispatchStatus status;
03061   DBusPendingCall *pending = data;
03062 
03063   connection = _dbus_pending_call_get_connection_and_lock (pending);
03064 
03065   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03066                                                    connection);
03067   _dbus_connection_remove_timeout_unlocked (connection,
03068                                             _dbus_pending_call_get_timeout_unlocked (pending));
03069   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03070 
03071   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03072   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03073 
03074   /* Unlocks, and calls out to user code */
03075   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03076   
03077   return TRUE;
03078 }
03079 
03117 dbus_bool_t
03118 dbus_connection_send_with_reply (DBusConnection     *connection,
03119                                  DBusMessage        *message,
03120                                  DBusPendingCall   **pending_return,
03121                                  int                 timeout_milliseconds)
03122 {
03123   DBusPendingCall *pending;
03124   dbus_int32_t serial = -1;
03125   DBusDispatchStatus status;
03126 
03127   _dbus_return_val_if_fail (connection != NULL, FALSE);
03128   _dbus_return_val_if_fail (message != NULL, FALSE);
03129   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03130 
03131   if (pending_return)
03132     *pending_return = NULL;
03133 
03134   CONNECTION_LOCK (connection);
03135 
03136    if (!_dbus_connection_get_is_connected_unlocked (connection))
03137     {
03138       CONNECTION_UNLOCK (connection);
03139 
03140       *pending_return = NULL;
03141 
03142       return TRUE;
03143     }
03144 
03145   pending = _dbus_pending_call_new_unlocked (connection,
03146                                              timeout_milliseconds,
03147                                              reply_handler_timeout);
03148 
03149   if (pending == NULL)
03150     {
03151       CONNECTION_UNLOCK (connection);
03152       return FALSE;
03153     }
03154 
03155   /* Assign a serial to the message */
03156   serial = dbus_message_get_serial (message);
03157   if (serial == 0)
03158     {
03159       serial = _dbus_connection_get_next_client_serial (connection);
03160       _dbus_message_set_serial (message, serial);
03161     }
03162 
03163   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03164     goto error;
03165     
03166   /* Insert the serial in the pending replies hash;
03167    * hash takes a refcount on DBusPendingCall.
03168    * Also, add the timeout.
03169    */
03170   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03171                                                       pending))
03172     goto error;
03173  
03174   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03175     {
03176       _dbus_connection_detach_pending_call_and_unlock (connection,
03177                                                        pending);
03178       goto error_unlocked;
03179     }
03180 
03181   if (pending_return)
03182     *pending_return = pending; /* hand off refcount */
03183   else
03184     {
03185       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03186       /* we still have a ref to the pending call in this case, we unref
03187        * after unlocking, below
03188        */
03189     }
03190 
03191   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03192 
03193   /* this calls out to user code */
03194   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03195 
03196   if (pending_return == NULL)
03197     dbus_pending_call_unref (pending);
03198   
03199   return TRUE;
03200 
03201  error:
03202   CONNECTION_UNLOCK (connection);
03203  error_unlocked:
03204   dbus_pending_call_unref (pending);
03205   return FALSE;
03206 }
03207 
03238 DBusMessage*
03239 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03240                                            DBusMessage        *message,
03241                                            int                 timeout_milliseconds,
03242                                            DBusError          *error)
03243 {
03244   DBusMessage *reply;
03245   DBusPendingCall *pending;
03246   
03247   _dbus_return_val_if_fail (connection != NULL, NULL);
03248   _dbus_return_val_if_fail (message != NULL, NULL);
03249   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03250   _dbus_return_val_if_error_is_set (error, NULL);
03251   
03252   if (!dbus_connection_send_with_reply (connection, message,
03253                                         &pending, timeout_milliseconds))
03254     {
03255       _DBUS_SET_OOM (error);
03256       return NULL;
03257     }
03258 
03259   if (pending == NULL)
03260     {
03261       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03262       return NULL;
03263     }
03264   
03265   dbus_pending_call_block (pending);
03266 
03267   reply = dbus_pending_call_steal_reply (pending);
03268   dbus_pending_call_unref (pending);
03269 
03270   /* call_complete_and_unlock() called from pending_call_block() should
03271    * always fill this in.
03272    */
03273   _dbus_assert (reply != NULL);
03274   
03275    if (dbus_set_error_from_message (error, reply))
03276     {
03277       dbus_message_unref (reply);
03278       return NULL;
03279     }
03280   else
03281     return reply;
03282 }
03283 
03292 DBusDispatchStatus
03293 _dbus_connection_flush_unlocked (DBusConnection *connection)
03294 {
03295   /* We have to specify DBUS_ITERATION_DO_READING here because
03296    * otherwise we could have two apps deadlock if they are both doing
03297    * a flush(), and the kernel buffers fill up. This could change the
03298    * dispatch status.
03299    */
03300   DBusDispatchStatus status;
03301 
03302   HAVE_LOCK_CHECK (connection);
03303   
03304   while (connection->n_outgoing > 0 &&
03305          _dbus_connection_get_is_connected_unlocked (connection))
03306     {
03307       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03308       HAVE_LOCK_CHECK (connection);
03309       _dbus_connection_do_iteration_unlocked (connection,
03310                                               DBUS_ITERATION_DO_READING |
03311                                               DBUS_ITERATION_DO_WRITING |
03312                                               DBUS_ITERATION_BLOCK,
03313                                               -1);
03314     }
03315 
03316   HAVE_LOCK_CHECK (connection);
03317   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03318   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03319 
03320   HAVE_LOCK_CHECK (connection);
03321   return status;
03322 }
03323 
03329 void
03330 dbus_connection_flush (DBusConnection *connection)
03331 {
03332   /* We have to specify DBUS_ITERATION_DO_READING here because
03333    * otherwise we could have two apps deadlock if they are both doing
03334    * a flush(), and the kernel buffers fill up. This could change the
03335    * dispatch status.
03336    */
03337   DBusDispatchStatus status;
03338 
03339   _dbus_return_if_fail (connection != NULL);
03340   
03341   CONNECTION_LOCK (connection);
03342 
03343   status = _dbus_connection_flush_unlocked (connection);
03344   
03345   HAVE_LOCK_CHECK (connection);
03346   /* Unlocks and calls out to user code */
03347   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03348 
03349   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03350 }
03351 
03362 static dbus_bool_t
03363 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03364                                      int             timeout_milliseconds, 
03365                                      dbus_bool_t     dispatch)
03366 {
03367   DBusDispatchStatus dstatus;
03368   dbus_bool_t no_progress_possible;
03369   
03370   dstatus = dbus_connection_get_dispatch_status (connection);
03371 
03372   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03373     {
03374       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03375       dbus_connection_dispatch (connection);
03376       CONNECTION_LOCK (connection);
03377     }
03378   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03379     {
03380       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03381       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03382       CONNECTION_LOCK (connection);
03383     }
03384   else
03385     {
03386       CONNECTION_LOCK (connection);
03387       if (_dbus_connection_get_is_connected_unlocked (connection))
03388         {
03389           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03390           _dbus_connection_do_iteration_unlocked (connection,
03391                                                   DBUS_ITERATION_DO_READING |
03392                                                   DBUS_ITERATION_DO_WRITING |
03393                                                   DBUS_ITERATION_BLOCK,
03394                                                   timeout_milliseconds);
03395         }
03396     }
03397   
03398   HAVE_LOCK_CHECK (connection);
03399   /* If we can dispatch, we can make progress until the Disconnected message
03400    * has been processed; if we can only read/write, we can make progress
03401    * as long as the transport is open.
03402    */
03403   if (dispatch)
03404     no_progress_possible = connection->n_incoming == 0 &&
03405       connection->disconnect_message_link == NULL;
03406   else
03407     no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03408   CONNECTION_UNLOCK (connection);
03409   return !no_progress_possible; /* TRUE if we can make more progress */
03410 }
03411 
03412 
03447 dbus_bool_t
03448 dbus_connection_read_write_dispatch (DBusConnection *connection,
03449                                      int             timeout_milliseconds)
03450 {
03451   _dbus_return_val_if_fail (connection != NULL, FALSE);
03452   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03453    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03454 }
03455 
03479 dbus_bool_t 
03480 dbus_connection_read_write (DBusConnection *connection, 
03481                             int             timeout_milliseconds) 
03482 { 
03483   _dbus_return_val_if_fail (connection != NULL, FALSE);
03484   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03485    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03486 }
03487 
03488 /* We need to call this anytime we pop the head of the queue, and then
03489  * update_dispatch_status_and_unlock needs to be called afterward
03490  * which will "process" the disconnected message and set
03491  * disconnected_message_processed.
03492  */
03493 static void
03494 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03495                                              DBusMessage    *head_of_queue)
03496 {
03497   HAVE_LOCK_CHECK (connection);
03498 
03499   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03500   if (connection->disconnect_message_link == NULL &&
03501       dbus_message_is_signal (head_of_queue,
03502                               DBUS_INTERFACE_LOCAL,
03503                               "Disconnected"))
03504     {
03505       connection->disconnected_message_arrived = TRUE;
03506     }
03507 }
03508 
03528 DBusMessage*
03529 dbus_connection_borrow_message (DBusConnection *connection)
03530 {
03531   DBusDispatchStatus status;
03532   DBusMessage *message;
03533 
03534   _dbus_return_val_if_fail (connection != NULL, NULL);
03535 
03536   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03537   
03538   /* this is called for the side effect that it queues
03539    * up any messages from the transport
03540    */
03541   status = dbus_connection_get_dispatch_status (connection);
03542   if (status != DBUS_DISPATCH_DATA_REMAINS)
03543     return NULL;
03544   
03545   CONNECTION_LOCK (connection);
03546 
03547   _dbus_connection_acquire_dispatch (connection);
03548 
03549   /* While a message is outstanding, the dispatch lock is held */
03550   _dbus_assert (connection->message_borrowed == NULL);
03551 
03552   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03553   
03554   message = connection->message_borrowed;
03555 
03556   check_disconnected_message_arrived_unlocked (connection, message);
03557   
03558   /* Note that we KEEP the dispatch lock until the message is returned */
03559   if (message == NULL)
03560     _dbus_connection_release_dispatch (connection);
03561 
03562   CONNECTION_UNLOCK (connection);
03563 
03564   /* We don't update dispatch status until it's returned or stolen */
03565   
03566   return message;
03567 }
03568 
03577 void
03578 dbus_connection_return_message (DBusConnection *connection,
03579                                 DBusMessage    *message)
03580 {
03581   DBusDispatchStatus status;
03582   
03583   _dbus_return_if_fail (connection != NULL);
03584   _dbus_return_if_fail (message != NULL);
03585   _dbus_return_if_fail (message == connection->message_borrowed);
03586   _dbus_return_if_fail (connection->dispatch_acquired);
03587   
03588   CONNECTION_LOCK (connection);
03589   
03590   _dbus_assert (message == connection->message_borrowed);
03591   
03592   connection->message_borrowed = NULL;
03593 
03594   _dbus_connection_release_dispatch (connection); 
03595 
03596   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03597   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03598 }
03599 
03609 void
03610 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03611                                         DBusMessage    *message)
03612 {
03613   DBusMessage *pop_message;
03614   DBusDispatchStatus status;
03615 
03616   _dbus_return_if_fail (connection != NULL);
03617   _dbus_return_if_fail (message != NULL);
03618   _dbus_return_if_fail (message == connection->message_borrowed);
03619   _dbus_return_if_fail (connection->dispatch_acquired);
03620   
03621   CONNECTION_LOCK (connection);
03622  
03623   _dbus_assert (message == connection->message_borrowed);
03624 
03625   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03626   _dbus_assert (message == pop_message);
03627   
03628   connection->n_incoming -= 1;
03629  
03630   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03631                  message, connection->n_incoming);
03632  
03633   connection->message_borrowed = NULL;
03634 
03635   _dbus_connection_release_dispatch (connection);
03636 
03637   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03638   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03639 }
03640 
03641 /* See dbus_connection_pop_message, but requires the caller to own
03642  * the lock before calling. May drop the lock while running.
03643  */
03644 static DBusList*
03645 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03646 {
03647   HAVE_LOCK_CHECK (connection);
03648   
03649   _dbus_assert (connection->message_borrowed == NULL);
03650   
03651   if (connection->n_incoming > 0)
03652     {
03653       DBusList *link;
03654 
03655       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03656       connection->n_incoming -= 1;
03657 
03658       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03659                      link->data,
03660                      dbus_message_get_type (link->data),
03661                      dbus_message_get_path (link->data) ?
03662                      dbus_message_get_path (link->data) :
03663                      "no path",
03664                      dbus_message_get_interface (link->data) ?
03665                      dbus_message_get_interface (link->data) :
03666                      "no interface",
03667                      dbus_message_get_member (link->data) ?
03668                      dbus_message_get_member (link->data) :
03669                      "no member",
03670                      dbus_message_get_signature (link->data),
03671                      connection, connection->n_incoming);
03672 
03673       check_disconnected_message_arrived_unlocked (connection, link->data);
03674       
03675       return link;
03676     }
03677   else
03678     return NULL;
03679 }
03680 
03681 /* See dbus_connection_pop_message, but requires the caller to own
03682  * the lock before calling. May drop the lock while running.
03683  */
03684 static DBusMessage*
03685 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03686 {
03687   DBusList *link;
03688 
03689   HAVE_LOCK_CHECK (connection);
03690   
03691   link = _dbus_connection_pop_message_link_unlocked (connection);
03692 
03693   if (link != NULL)
03694     {
03695       DBusMessage *message;
03696       
03697       message = link->data;
03698       
03699       _dbus_list_free_link (link);
03700       
03701       return message;
03702     }
03703   else
03704     return NULL;
03705 }
03706 
03707 static void
03708 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03709                                                 DBusList       *message_link)
03710 {
03711   HAVE_LOCK_CHECK (connection);
03712   
03713   _dbus_assert (message_link != NULL);
03714   /* You can't borrow a message while a link is outstanding */
03715   _dbus_assert (connection->message_borrowed == NULL);
03716   /* We had to have the dispatch lock across the pop/putback */
03717   _dbus_assert (connection->dispatch_acquired);
03718 
03719   _dbus_list_prepend_link (&connection->incoming_messages,
03720                            message_link);
03721   connection->n_incoming += 1;
03722 
03723   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03724                  message_link->data,
03725                  dbus_message_get_type (message_link->data),
03726                  dbus_message_get_interface (message_link->data) ?
03727                  dbus_message_get_interface (message_link->data) :
03728                  "no interface",
03729                  dbus_message_get_member (message_link->data) ?
03730                  dbus_message_get_member (message_link->data) :
03731                  "no member",
03732                  dbus_message_get_signature (message_link->data),
03733                  connection, connection->n_incoming);
03734 }
03735 
03755 DBusMessage*
03756 dbus_connection_pop_message (DBusConnection *connection)
03757 {
03758   DBusMessage *message;
03759   DBusDispatchStatus status;
03760 
03761   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03762   
03763   /* this is called for the side effect that it queues
03764    * up any messages from the transport
03765    */
03766   status = dbus_connection_get_dispatch_status (connection);
03767   if (status != DBUS_DISPATCH_DATA_REMAINS)
03768     return NULL;
03769   
03770   CONNECTION_LOCK (connection);
03771   _dbus_connection_acquire_dispatch (connection);
03772   HAVE_LOCK_CHECK (connection);
03773   
03774   message = _dbus_connection_pop_message_unlocked (connection);
03775 
03776   _dbus_verbose ("Returning popped message %p\n", message);    
03777 
03778   _dbus_connection_release_dispatch (connection);
03779 
03780   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03781   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03782   
03783   return message;
03784 }
03785 
03793 static void
03794 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03795 {
03796   HAVE_LOCK_CHECK (connection);
03797 
03798   _dbus_connection_ref_unlocked (connection);
03799   CONNECTION_UNLOCK (connection);
03800   
03801   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03802   _dbus_mutex_lock (connection->dispatch_mutex);
03803 
03804   while (connection->dispatch_acquired)
03805     {
03806       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03807       _dbus_condvar_wait (connection->dispatch_cond, 
03808                           connection->dispatch_mutex);
03809     }
03810   
03811   _dbus_assert (!connection->dispatch_acquired);
03812 
03813   connection->dispatch_acquired = TRUE;
03814 
03815   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03816   _dbus_mutex_unlock (connection->dispatch_mutex);
03817   
03818   CONNECTION_LOCK (connection);
03819   _dbus_connection_unref_unlocked (connection);
03820 }
03821 
03829 static void
03830 _dbus_connection_release_dispatch (DBusConnection *connection)
03831 {
03832   HAVE_LOCK_CHECK (connection);
03833   
03834   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03835   _dbus_mutex_lock (connection->dispatch_mutex);
03836   
03837   _dbus_assert (connection->dispatch_acquired);
03838 
03839   connection->dispatch_acquired = FALSE;
03840   _dbus_condvar_wake_one (connection->dispatch_cond);
03841 
03842   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03843   _dbus_mutex_unlock (connection->dispatch_mutex);
03844 }
03845 
03846 static void
03847 _dbus_connection_failed_pop (DBusConnection *connection,
03848                              DBusList       *message_link)
03849 {
03850   _dbus_list_prepend_link (&connection->incoming_messages,
03851                            message_link);
03852   connection->n_incoming += 1;
03853 }
03854 
03855 /* Note this may be called multiple times since we don't track whether we already did it */
03856 static void
03857 notify_disconnected_unlocked (DBusConnection *connection)
03858 {
03859   HAVE_LOCK_CHECK (connection);
03860 
03861   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
03862    * connection from dbus_bus_get(). We make the same guarantee for
03863    * dbus_connection_open() but in a different way since we don't want to
03864    * unref right here; we instead check for connectedness before returning
03865    * the connection from the hash.
03866    */
03867   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03868 
03869   /* Dump the outgoing queue, we aren't going to be able to
03870    * send it now, and we'd like accessors like
03871    * dbus_connection_get_outgoing_size() to be accurate.
03872    */
03873   if (connection->n_outgoing > 0)
03874     {
03875       DBusList *link;
03876       
03877       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03878                      connection->n_outgoing);
03879       
03880       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03881         {
03882           _dbus_connection_message_sent (connection, link->data);
03883         }
03884     } 
03885 }
03886 
03887 /* Note this may be called multiple times since we don't track whether we already did it */
03888 static DBusDispatchStatus
03889 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03890 {
03891   HAVE_LOCK_CHECK (connection);
03892   
03893   if (connection->disconnect_message_link != NULL)
03894     {
03895       _dbus_verbose ("Sending disconnect message from %s\n",
03896                      _DBUS_FUNCTION_NAME);
03897       
03898       /* If we have pending calls, queue their timeouts - we want the Disconnected
03899        * to be the last message, after these timeouts.
03900        */
03901       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03902       
03903       /* We haven't sent the disconnect message already,
03904        * and all real messages have been queued up.
03905        */
03906       _dbus_connection_queue_synthesized_message_link (connection,
03907                                                        connection->disconnect_message_link);
03908       connection->disconnect_message_link = NULL;
03909 
03910       return DBUS_DISPATCH_DATA_REMAINS;
03911     }
03912 
03913   return DBUS_DISPATCH_COMPLETE;
03914 }
03915 
03916 static DBusDispatchStatus
03917 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03918 {
03919   HAVE_LOCK_CHECK (connection);
03920   
03921   if (connection->n_incoming > 0)
03922     return DBUS_DISPATCH_DATA_REMAINS;
03923   else if (!_dbus_transport_queue_messages (connection->transport))
03924     return DBUS_DISPATCH_NEED_MEMORY;
03925   else
03926     {
03927       DBusDispatchStatus status;
03928       dbus_bool_t is_connected;
03929       
03930       status = _dbus_transport_get_dispatch_status (connection->transport);
03931       is_connected = _dbus_transport_get_is_connected (connection->transport);
03932 
03933       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03934                      DISPATCH_STATUS_NAME (status), is_connected);
03935       
03936       if (!is_connected)
03937         {
03938           /* It's possible this would be better done by having an explicit
03939            * notification from _dbus_transport_disconnect() that would
03940            * synchronously do this, instead of waiting for the next dispatch
03941            * status check. However, probably not good to change until it causes
03942            * a problem.
03943            */
03944           notify_disconnected_unlocked (connection);
03945 
03946           /* I'm not sure this is needed; the idea is that we want to
03947            * queue the Disconnected only after we've read all the
03948            * messages, but if we're disconnected maybe we are guaranteed
03949            * to have read them all ?
03950            */
03951           if (status == DBUS_DISPATCH_COMPLETE)
03952             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03953         }
03954       
03955       if (status != DBUS_DISPATCH_COMPLETE)
03956         return status;
03957       else if (connection->n_incoming > 0)
03958         return DBUS_DISPATCH_DATA_REMAINS;
03959       else
03960         return DBUS_DISPATCH_COMPLETE;
03961     }
03962 }
03963 
03964 static void
03965 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03966                                                     DBusDispatchStatus new_status)
03967 {
03968   dbus_bool_t changed;
03969   DBusDispatchStatusFunction function;
03970   void *data;
03971 
03972   HAVE_LOCK_CHECK (connection);
03973 
03974   _dbus_connection_ref_unlocked (connection);
03975 
03976   changed = new_status != connection->last_dispatch_status;
03977 
03978   connection->last_dispatch_status = new_status;
03979 
03980   function = connection->dispatch_status_function;
03981   data = connection->dispatch_status_data;
03982 
03983   if (connection->disconnected_message_arrived &&
03984       !connection->disconnected_message_processed)
03985     {
03986       connection->disconnected_message_processed = TRUE;
03987       
03988       /* this does an unref, but we have a ref
03989        * so we should not run the finalizer here
03990        * inside the lock.
03991        */
03992       connection_forget_shared_unlocked (connection);
03993 
03994       if (connection->exit_on_disconnect)
03995         {
03996           CONNECTION_UNLOCK (connection);            
03997           
03998           _dbus_verbose ("Exiting on Disconnected signal\n");
03999           _dbus_exit (1);
04000           _dbus_assert_not_reached ("Call to exit() returned");
04001         }
04002     }
04003   
04004   /* We drop the lock */
04005   CONNECTION_UNLOCK (connection);
04006   
04007   if (changed && function)
04008     {
04009       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04010                      connection, new_status,
04011                      DISPATCH_STATUS_NAME (new_status));
04012       (* function) (connection, new_status, data);      
04013     }
04014   
04015   dbus_connection_unref (connection);
04016 }
04017 
04043 DBusDispatchStatus
04044 dbus_connection_get_dispatch_status (DBusConnection *connection)
04045 {
04046   DBusDispatchStatus status;
04047 
04048   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04049 
04050   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04051   
04052   CONNECTION_LOCK (connection);
04053 
04054   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04055   
04056   CONNECTION_UNLOCK (connection);
04057 
04058   return status;
04059 }
04060 
04064 static DBusHandlerResult
04065 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04066                                                  DBusMessage    *message)
04067 {
04068   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04069     {
04070       /* This means we're letting the bus route this message */
04071       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04072     }
04073   else if (dbus_message_is_method_call (message,
04074                                         DBUS_INTERFACE_PEER,
04075                                         "Ping"))
04076     {
04077       DBusMessage *ret;
04078       dbus_bool_t sent;
04079       
04080       ret = dbus_message_new_method_return (message);
04081       if (ret == NULL)
04082         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04083      
04084       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04085 
04086       dbus_message_unref (ret);
04087 
04088       if (!sent)
04089         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04090       
04091       return DBUS_HANDLER_RESULT_HANDLED;
04092     }
04093   else if (dbus_message_is_method_call (message,
04094                                         DBUS_INTERFACE_PEER,
04095                                         "GetMachineId"))
04096     {
04097       DBusMessage *ret;
04098       dbus_bool_t sent;
04099       DBusString uuid;
04100       
04101       ret = dbus_message_new_method_return (message);
04102       if (ret == NULL)
04103         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04104 
04105       sent = FALSE;
04106       _dbus_string_init (&uuid);
04107       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04108         {
04109           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04110           if (dbus_message_append_args (ret,
04111                                         DBUS_TYPE_STRING, &v_STRING,
04112                                         DBUS_TYPE_INVALID))
04113             {
04114               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04115             }
04116         }
04117       _dbus_string_free (&uuid);
04118       
04119       dbus_message_unref (ret);
04120 
04121       if (!sent)
04122         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04123       
04124       return DBUS_HANDLER_RESULT_HANDLED;
04125     }
04126   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04127     {
04128       /* We need to bounce anything else with this interface, otherwise apps
04129        * could start extending the interface and when we added extensions
04130        * here to DBusConnection we'd break those apps.
04131        */
04132       
04133       DBusMessage *ret;
04134       dbus_bool_t sent;
04135       
04136       ret = dbus_message_new_error (message,
04137                                     DBUS_ERROR_UNKNOWN_METHOD,
04138                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04139       if (ret == NULL)
04140         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04141       
04142       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04143       
04144       dbus_message_unref (ret);
04145       
04146       if (!sent)
04147         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04148       
04149       return DBUS_HANDLER_RESULT_HANDLED;
04150     }
04151   else
04152     {
04153       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04154     }
04155 }
04156 
04163 static DBusHandlerResult
04164 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04165                                                            DBusMessage    *message)
04166 {
04167   /* We just run one filter for now but have the option to run more
04168      if the spec calls for it in the future */
04169 
04170   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04171 }
04172 
04215 DBusDispatchStatus
04216 dbus_connection_dispatch (DBusConnection *connection)
04217 {
04218   DBusMessage *message;
04219   DBusList *link, *filter_list_copy, *message_link;
04220   DBusHandlerResult result;
04221   DBusPendingCall *pending;
04222   dbus_int32_t reply_serial;
04223   DBusDispatchStatus status;
04224 
04225   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04226 
04227   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04228   
04229   CONNECTION_LOCK (connection);
04230   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04231   if (status != DBUS_DISPATCH_DATA_REMAINS)
04232     {
04233       /* unlocks and calls out to user code */
04234       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04235       return status;
04236     }
04237   
04238   /* We need to ref the connection since the callback could potentially
04239    * drop the last ref to it
04240    */
04241   _dbus_connection_ref_unlocked (connection);
04242 
04243   _dbus_connection_acquire_dispatch (connection);
04244   HAVE_LOCK_CHECK (connection);
04245 
04246   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04247   if (message_link == NULL)
04248     {
04249       /* another thread dispatched our stuff */
04250 
04251       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04252       
04253       _dbus_connection_release_dispatch (connection);
04254 
04255       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04256 
04257       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04258       
04259       dbus_connection_unref (connection);
04260       
04261       return status;
04262     }
04263 
04264   message = message_link->data;
04265 
04266   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04267                  message,
04268                  dbus_message_get_type (message),
04269                  dbus_message_get_interface (message) ?
04270                  dbus_message_get_interface (message) :
04271                  "no interface",
04272                  dbus_message_get_member (message) ?
04273                  dbus_message_get_member (message) :
04274                  "no member",
04275                  dbus_message_get_signature (message));
04276 
04277   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04278   
04279   /* Pending call handling must be first, because if you do
04280    * dbus_connection_send_with_reply_and_block() or
04281    * dbus_pending_call_block() then no handlers/filters will be run on
04282    * the reply. We want consistent semantics in the case where we
04283    * dbus_connection_dispatch() the reply.
04284    */
04285   
04286   reply_serial = dbus_message_get_reply_serial (message);
04287   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04288                                          reply_serial);
04289   if (pending)
04290     {
04291       _dbus_verbose ("Dispatching a pending reply\n");
04292       complete_pending_call_and_unlock (connection, pending, message);
04293       pending = NULL; /* it's probably unref'd */
04294       
04295       CONNECTION_LOCK (connection);
04296       _dbus_verbose ("pending call completed in dispatch\n");
04297       result = DBUS_HANDLER_RESULT_HANDLED;
04298       goto out;
04299     }
04300 
04301   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04302   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04303     goto out;
04304  
04305   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04306     {
04307       _dbus_connection_release_dispatch (connection);
04308       HAVE_LOCK_CHECK (connection);
04309       
04310       _dbus_connection_failed_pop (connection, message_link);
04311 
04312       /* unlocks and calls user code */
04313       _dbus_connection_update_dispatch_status_and_unlock (connection,
04314                                                           DBUS_DISPATCH_NEED_MEMORY);
04315 
04316       if (pending)
04317         dbus_pending_call_unref (pending);
04318       dbus_connection_unref (connection);
04319       
04320       return DBUS_DISPATCH_NEED_MEMORY;
04321     }
04322   
04323   _dbus_list_foreach (&filter_list_copy,
04324                       (DBusForeachFunction)_dbus_message_filter_ref,
04325                       NULL);
04326 
04327   /* We're still protected from dispatch() reentrancy here
04328    * since we acquired the dispatcher
04329    */
04330   CONNECTION_UNLOCK (connection);
04331   
04332   link = _dbus_list_get_first_link (&filter_list_copy);
04333   while (link != NULL)
04334     {
04335       DBusMessageFilter *filter = link->data;
04336       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04337 
04338       if (filter->function == NULL)
04339         {
04340           _dbus_verbose ("  filter was removed in a callback function\n");
04341           link = next;
04342           continue;
04343         }
04344 
04345       _dbus_verbose ("  running filter on message %p\n", message);
04346       result = (* filter->function) (connection, message, filter->user_data);
04347 
04348       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04349         break;
04350 
04351       link = next;
04352     }
04353 
04354   _dbus_list_foreach (&filter_list_copy,
04355                       (DBusForeachFunction)_dbus_message_filter_unref,
04356                       NULL);
04357   _dbus_list_clear (&filter_list_copy);
04358   
04359   CONNECTION_LOCK (connection);
04360 
04361   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04362     {
04363       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04364       goto out;
04365     }
04366   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04367     {
04368       _dbus_verbose ("filter handled message in dispatch\n");
04369       goto out;
04370     }
04371 
04372   /* We're still protected from dispatch() reentrancy here
04373    * since we acquired the dispatcher
04374    */
04375   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
04376                  message,
04377                  dbus_message_get_type (message),
04378                  dbus_message_get_interface (message) ?
04379                  dbus_message_get_interface (message) :
04380                  "no interface",
04381                  dbus_message_get_member (message) ?
04382                  dbus_message_get_member (message) :
04383                  "no member",
04384                  dbus_message_get_signature (message));
04385 
04386   HAVE_LOCK_CHECK (connection);
04387   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04388                                                   message);
04389   
04390   CONNECTION_LOCK (connection);
04391 
04392   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04393     {
04394       _dbus_verbose ("object tree handled message in dispatch\n");
04395       goto out;
04396     }
04397 
04398   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04399     {
04400       DBusMessage *reply;
04401       DBusString str;
04402       DBusPreallocatedSend *preallocated;
04403 
04404       _dbus_verbose ("  sending error %s\n",
04405                      DBUS_ERROR_UNKNOWN_METHOD);
04406       
04407       if (!_dbus_string_init (&str))
04408         {
04409           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04410           _dbus_verbose ("no memory for error string in dispatch\n");
04411           goto out;
04412         }
04413               
04414       if (!_dbus_string_append_printf (&str,
04415                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04416                                        dbus_message_get_member (message),
04417                                        dbus_message_get_signature (message),
04418                                        dbus_message_get_interface (message)))
04419         {
04420           _dbus_string_free (&str);
04421           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04422           _dbus_verbose ("no memory for error string in dispatch\n");
04423           goto out;
04424         }
04425       
04426       reply = dbus_message_new_error (message,
04427                                       DBUS_ERROR_UNKNOWN_METHOD,
04428                                       _dbus_string_get_const_data (&str));
04429       _dbus_string_free (&str);
04430 
04431       if (reply == NULL)
04432         {
04433           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04434           _dbus_verbose ("no memory for error reply in dispatch\n");
04435           goto out;
04436         }
04437       
04438       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04439 
04440       if (preallocated == NULL)
04441         {
04442           dbus_message_unref (reply);
04443           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04444           _dbus_verbose ("no memory for error send in dispatch\n");
04445           goto out;
04446         }
04447 
04448       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04449                                                              reply, NULL);
04450 
04451       dbus_message_unref (reply);
04452       
04453       result = DBUS_HANDLER_RESULT_HANDLED;
04454     }
04455   
04456   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04457                  dbus_message_get_type (message),
04458                  dbus_message_get_interface (message) ?
04459                  dbus_message_get_interface (message) :
04460                  "no interface",
04461                  dbus_message_get_member (message) ?
04462                  dbus_message_get_member (message) :
04463                  "no member",
04464                  dbus_message_get_signature (message),
04465                  connection);
04466   
04467  out:
04468   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04469     {
04470       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04471       
04472       /* Put message back, and we'll start over.
04473        * Yes this means handlers must be idempotent if they
04474        * don't return HANDLED; c'est la vie.
04475        */
04476       _dbus_connection_putback_message_link_unlocked (connection,
04477                                                       message_link);
04478     }
04479   else
04480     {
04481       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04482       
04483       _dbus_list_free_link (message_link);
04484       dbus_message_unref (message); /* don't want the message to count in max message limits
04485                                      * in computing dispatch status below
04486                                      */
04487     }
04488   
04489   _dbus_connection_release_dispatch (connection);
04490   HAVE_LOCK_CHECK (connection);
04491 
04492   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04493   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04494 
04495   /* unlocks and calls user code */
04496   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04497   
04498   dbus_connection_unref (connection);
04499   
04500   return status;
04501 }
04502 
04562 dbus_bool_t
04563 dbus_connection_set_watch_functions (DBusConnection              *connection,
04564                                      DBusAddWatchFunction         add_function,
04565                                      DBusRemoveWatchFunction      remove_function,
04566                                      DBusWatchToggledFunction     toggled_function,
04567                                      void                        *data,
04568                                      DBusFreeFunction             free_data_function)
04569 {
04570   dbus_bool_t retval;
04571   DBusWatchList *watches;
04572 
04573   _dbus_return_val_if_fail (connection != NULL, FALSE);
04574   
04575   CONNECTION_LOCK (connection);
04576 
04577 #ifndef DBUS_DISABLE_CHECKS
04578   if (connection->watches == NULL)
04579     {
04580       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04581                                _DBUS_FUNCTION_NAME);
04582       return FALSE;
04583     }
04584 #endif
04585   
04586   /* ref connection for slightly better reentrancy */
04587   _dbus_connection_ref_unlocked (connection);
04588 
04589   /* This can call back into user code, and we need to drop the
04590    * connection lock when it does. This is kind of a lame
04591    * way to do it.
04592    */
04593   watches = connection->watches;
04594   connection->watches = NULL;
04595   CONNECTION_UNLOCK (connection);
04596 
04597   retval = _dbus_watch_list_set_functions (watches,
04598                                            add_function, remove_function,
04599                                            toggled_function,
04600                                            data, free_data_function);
04601   CONNECTION_LOCK (connection);
04602   connection->watches = watches;
04603   
04604   CONNECTION_UNLOCK (connection);
04605   /* drop our paranoid refcount */
04606   dbus_connection_unref (connection);
04607   
04608   return retval;
04609 }
04610 
04644 dbus_bool_t
04645 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04646                                          DBusAddTimeoutFunction     add_function,
04647                                          DBusRemoveTimeoutFunction  remove_function,
04648                                          DBusTimeoutToggledFunction toggled_function,
04649                                          void                      *data,
04650                                          DBusFreeFunction           free_data_function)
04651 {
04652   dbus_bool_t retval;
04653   DBusTimeoutList *timeouts;
04654 
04655   _dbus_return_val_if_fail (connection != NULL, FALSE);
04656   
04657   CONNECTION_LOCK (connection);
04658 
04659 #ifndef DBUS_DISABLE_CHECKS
04660   if (connection->timeouts == NULL)
04661     {
04662       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04663                                _DBUS_FUNCTION_NAME);
04664       return FALSE;
04665     }
04666 #endif
04667   
04668   /* ref connection for slightly better reentrancy */
04669   _dbus_connection_ref_unlocked (connection);
04670 
04671   timeouts = connection->timeouts;
04672   connection->timeouts = NULL;
04673   CONNECTION_UNLOCK (connection);
04674   
04675   retval = _dbus_timeout_list_set_functions (timeouts,
04676                                              add_function, remove_function,
04677                                              toggled_function,
04678                                              data, free_data_function);
04679   CONNECTION_LOCK (connection);
04680   connection->timeouts = timeouts;
04681   
04682   CONNECTION_UNLOCK (connection);
04683   /* drop our paranoid refcount */
04684   dbus_connection_unref (connection);
04685 
04686   return retval;
04687 }
04688 
04703 void
04704 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04705                                           DBusWakeupMainFunction     wakeup_main_function,
04706                                           void                      *data,
04707                                           DBusFreeFunction           free_data_function)
04708 {
04709   void *old_data;
04710   DBusFreeFunction old_free_data;
04711 
04712   _dbus_return_if_fail (connection != NULL);
04713   
04714   CONNECTION_LOCK (connection);
04715   old_data = connection->wakeup_main_data;
04716   old_free_data = connection->free_wakeup_main_data;
04717 
04718   connection->wakeup_main_function = wakeup_main_function;
04719   connection->wakeup_main_data = data;
04720   connection->free_wakeup_main_data = free_data_function;
04721   
04722   CONNECTION_UNLOCK (connection);
04723 
04724   /* Callback outside the lock */
04725   if (old_free_data)
04726     (*old_free_data) (old_data);
04727 }
04728 
04749 void
04750 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04751                                               DBusDispatchStatusFunction  function,
04752                                               void                       *data,
04753                                               DBusFreeFunction            free_data_function)
04754 {
04755   void *old_data;
04756   DBusFreeFunction old_free_data;
04757 
04758   _dbus_return_if_fail (connection != NULL);
04759   
04760   CONNECTION_LOCK (connection);
04761   old_data = connection->dispatch_status_data;
04762   old_free_data = connection->free_dispatch_status_data;
04763 
04764   connection->dispatch_status_function = function;
04765   connection->dispatch_status_data = data;
04766   connection->free_dispatch_status_data = free_data_function;
04767   
04768   CONNECTION_UNLOCK (connection);
04769 
04770   /* Callback outside the lock */
04771   if (old_free_data)
04772     (*old_free_data) (old_data);
04773 }
04774 
04794 dbus_bool_t
04795 dbus_connection_get_unix_fd (DBusConnection *connection,
04796                              int            *fd)
04797 {
04798   _dbus_return_val_if_fail (connection != NULL, FALSE);
04799   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04800 
04801 #ifdef DBUS_WIN
04802   /* FIXME do this on a lower level */
04803   return FALSE;
04804 #endif
04805   
04806   return dbus_connection_get_socket(connection, fd);
04807 }
04808 
04824 dbus_bool_t
04825 dbus_connection_get_socket(DBusConnection              *connection,
04826                            int                         *fd)
04827 {
04828   dbus_bool_t retval;
04829 
04830   _dbus_return_val_if_fail (connection != NULL, FALSE);
04831   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04832   
04833   CONNECTION_LOCK (connection);
04834   
04835   retval = _dbus_transport_get_socket_fd (connection->transport,
04836                                           fd);
04837 
04838   CONNECTION_UNLOCK (connection);
04839 
04840   return retval;
04841 }
04842 
04843 
04866 dbus_bool_t
04867 dbus_connection_get_unix_user (DBusConnection *connection,
04868                                unsigned long  *uid)
04869 {
04870   dbus_bool_t result;
04871 
04872   _dbus_return_val_if_fail (connection != NULL, FALSE);
04873   _dbus_return_val_if_fail (uid != NULL, FALSE);
04874   
04875   CONNECTION_LOCK (connection);
04876 
04877   if (!_dbus_transport_get_is_authenticated (connection->transport))
04878     result = FALSE;
04879   else
04880     result = _dbus_transport_get_unix_user (connection->transport,
04881                                             uid);
04882 
04883 #ifdef DBUS_WIN
04884   _dbus_assert (!result);
04885 #endif
04886   
04887   CONNECTION_UNLOCK (connection);
04888 
04889   return result;
04890 }
04891 
04902 dbus_bool_t
04903 dbus_connection_get_unix_process_id (DBusConnection *connection,
04904                                      unsigned long  *pid)
04905 {
04906   dbus_bool_t result;
04907 
04908   _dbus_return_val_if_fail (connection != NULL, FALSE);
04909   _dbus_return_val_if_fail (pid != NULL, FALSE);
04910   
04911   CONNECTION_LOCK (connection);
04912 
04913   if (!_dbus_transport_get_is_authenticated (connection->transport))
04914     result = FALSE;
04915   else
04916     result = _dbus_transport_get_unix_process_id (connection->transport,
04917                                                   pid);
04918 #ifdef DBUS_WIN
04919   _dbus_assert (!result);
04920 #endif
04921   
04922   CONNECTION_UNLOCK (connection);
04923 
04924   return result;
04925 }
04926 
04949 void
04950 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04951                                         DBusAllowUnixUserFunction   function,
04952                                         void                       *data,
04953                                         DBusFreeFunction            free_data_function)
04954 {
04955   void *old_data = NULL;
04956   DBusFreeFunction old_free_function = NULL;
04957 
04958   _dbus_return_if_fail (connection != NULL);
04959   
04960   CONNECTION_LOCK (connection);
04961   _dbus_transport_set_unix_user_function (connection->transport,
04962                                           function, data, free_data_function,
04963                                           &old_data, &old_free_function);
04964   CONNECTION_UNLOCK (connection);
04965 
04966   if (old_free_function != NULL)
04967     (* old_free_function) (old_data);
04968 }
04969 
05001 dbus_bool_t
05002 dbus_connection_get_windows_user (DBusConnection             *connection,
05003                                   char                      **windows_sid_p)
05004 {
05005   dbus_bool_t result;
05006 
05007   _dbus_return_val_if_fail (connection != NULL, FALSE);
05008   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05009   
05010   CONNECTION_LOCK (connection);
05011 
05012   if (!_dbus_transport_get_is_authenticated (connection->transport))
05013     result = FALSE;
05014   else
05015     result = _dbus_transport_get_windows_user (connection->transport,
05016                                                windows_sid_p);
05017 
05018 #ifdef DBUS_UNIX
05019   _dbus_assert (!result);
05020 #endif
05021   
05022   CONNECTION_UNLOCK (connection);
05023 
05024   return result;
05025 }
05026 
05048 void
05049 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05050                                            DBusAllowWindowsUserFunction function,
05051                                            void                        *data,
05052                                            DBusFreeFunction             free_data_function)
05053 {
05054   void *old_data = NULL;
05055   DBusFreeFunction old_free_function = NULL;
05056 
05057   _dbus_return_if_fail (connection != NULL);
05058   
05059   CONNECTION_LOCK (connection);
05060   _dbus_transport_set_windows_user_function (connection->transport,
05061                                              function, data, free_data_function,
05062                                              &old_data, &old_free_function);
05063   CONNECTION_UNLOCK (connection);
05064 
05065   if (old_free_function != NULL)
05066     (* old_free_function) (old_data);
05067 }
05068 
05095 void
05096 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05097                                      dbus_bool_t                 value)
05098 {
05099   _dbus_return_if_fail (connection != NULL);
05100   
05101   CONNECTION_LOCK (connection);
05102   _dbus_transport_set_allow_anonymous (connection->transport, value);
05103   CONNECTION_UNLOCK (connection);
05104 }
05105 
05123 void
05124 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05125                                          dbus_bool_t                 value)
05126 {
05127   _dbus_return_if_fail (connection != NULL);
05128   
05129   CONNECTION_LOCK (connection);
05130   connection->route_peer_messages = TRUE;
05131   CONNECTION_UNLOCK (connection);
05132 }
05133 
05155 dbus_bool_t
05156 dbus_connection_add_filter (DBusConnection            *connection,
05157                             DBusHandleMessageFunction  function,
05158                             void                      *user_data,
05159                             DBusFreeFunction           free_data_function)
05160 {
05161   DBusMessageFilter *filter;
05162   
05163   _dbus_return_val_if_fail (connection != NULL, FALSE);
05164   _dbus_return_val_if_fail (function != NULL, FALSE);
05165 
05166   filter = dbus_new0 (DBusMessageFilter, 1);
05167   if (filter == NULL)
05168     return FALSE;
05169 
05170   filter->refcount.value = 1;
05171   
05172   CONNECTION_LOCK (connection);
05173 
05174   if (!_dbus_list_append (&connection->filter_list,
05175                           filter))
05176     {
05177       _dbus_message_filter_unref (filter);
05178       CONNECTION_UNLOCK (connection);
05179       return FALSE;
05180     }
05181 
05182   /* Fill in filter after all memory allocated,
05183    * so we don't run the free_user_data_function
05184    * if the add_filter() fails
05185    */
05186   
05187   filter->function = function;
05188   filter->user_data = user_data;
05189   filter->free_user_data_function = free_data_function;
05190         
05191   CONNECTION_UNLOCK (connection);
05192   return TRUE;
05193 }
05194 
05207 void
05208 dbus_connection_remove_filter (DBusConnection            *connection,
05209                                DBusHandleMessageFunction  function,
05210                                void                      *user_data)
05211 {
05212   DBusList *link;
05213   DBusMessageFilter *filter;
05214   
05215   _dbus_return_if_fail (connection != NULL);
05216   _dbus_return_if_fail (function != NULL);
05217   
05218   CONNECTION_LOCK (connection);
05219 
05220   filter = NULL;
05221   
05222   link = _dbus_list_get_last_link (&connection->filter_list);
05223   while (link != NULL)
05224     {
05225       filter = link->data;
05226 
05227       if (filter->function == function &&
05228           filter->user_data == user_data)
05229         {
05230           _dbus_list_remove_link (&connection->filter_list, link);
05231           filter->function = NULL;
05232           
05233           break;
05234         }
05235         
05236       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05237     }
05238   
05239   CONNECTION_UNLOCK (connection);
05240 
05241 #ifndef DBUS_DISABLE_CHECKS
05242   if (filter == NULL)
05243     {
05244       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05245                                function, user_data);
05246       return;
05247     }
05248 #endif
05249   
05250   /* Call application code */
05251   if (filter->free_user_data_function)
05252     (* filter->free_user_data_function) (filter->user_data);
05253 
05254   filter->free_user_data_function = NULL;
05255   filter->user_data = NULL;
05256   
05257   _dbus_message_filter_unref (filter);
05258 }
05259 
05271 dbus_bool_t
05272 dbus_connection_register_object_path (DBusConnection              *connection,
05273                                       const char                  *path,
05274                                       const DBusObjectPathVTable  *vtable,
05275                                       void                        *user_data)
05276 {
05277   char **decomposed_path;
05278   dbus_bool_t retval;
05279   
05280   _dbus_return_val_if_fail (connection != NULL, FALSE);
05281   _dbus_return_val_if_fail (path != NULL, FALSE);
05282   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05283   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05284 
05285   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05286     return FALSE;
05287 
05288   CONNECTION_LOCK (connection);
05289 
05290   retval = _dbus_object_tree_register (connection->objects,
05291                                        FALSE,
05292                                        (const char **) decomposed_path, vtable,
05293                                        user_data);
05294 
05295   CONNECTION_UNLOCK (connection);
05296 
05297   dbus_free_string_array (decomposed_path);
05298 
05299   return retval;
05300 }
05301 
05314 dbus_bool_t
05315 dbus_connection_register_fallback (DBusConnection              *connection,
05316                                    const char                  *path,
05317                                    const DBusObjectPathVTable  *vtable,
05318                                    void                        *user_data)
05319 {
05320   char **decomposed_path;
05321   dbus_bool_t retval;
05322   
05323   _dbus_return_val_if_fail (connection != NULL, FALSE);
05324   _dbus_return_val_if_fail (path != NULL, FALSE);
05325   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05326   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05327 
05328   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05329     return FALSE;
05330 
05331   CONNECTION_LOCK (connection);
05332 
05333   retval = _dbus_object_tree_register (connection->objects,
05334                                        TRUE,
05335                                        (const char **) decomposed_path, vtable,
05336                                        user_data);
05337 
05338   CONNECTION_UNLOCK (connection);
05339 
05340   dbus_free_string_array (decomposed_path);
05341 
05342   return retval;
05343 }
05344 
05354 dbus_bool_t
05355 dbus_connection_unregister_object_path (DBusConnection              *connection,
05356                                         const char                  *path)
05357 {
05358   char **decomposed_path;
05359 
05360   _dbus_return_val_if_fail (connection != NULL, FALSE);
05361   _dbus_return_val_if_fail (path != NULL, FALSE);
05362   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05363 
05364   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05365       return FALSE;
05366 
05367   CONNECTION_LOCK (connection);
05368 
05369   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05370 
05371   dbus_free_string_array (decomposed_path);
05372 
05373   return TRUE;
05374 }
05375 
05386 dbus_bool_t
05387 dbus_connection_get_object_path_data (DBusConnection *connection,
05388                                       const char     *path,
05389                                       void          **data_p)
05390 {
05391   char **decomposed_path;
05392 
05393   _dbus_return_val_if_fail (connection != NULL, FALSE);
05394   _dbus_return_val_if_fail (path != NULL, FALSE);
05395   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05396 
05397   *data_p = NULL;
05398   
05399   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05400     return FALSE;
05401   
05402   CONNECTION_LOCK (connection);
05403 
05404   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05405 
05406   CONNECTION_UNLOCK (connection);
05407 
05408   dbus_free_string_array (decomposed_path);
05409 
05410   return TRUE;
05411 }
05412 
05423 dbus_bool_t
05424 dbus_connection_list_registered (DBusConnection              *connection,
05425                                  const char                  *parent_path,
05426                                  char                      ***child_entries)
05427 {
05428   char **decomposed_path;
05429   dbus_bool_t retval;
05430   _dbus_return_val_if_fail (connection != NULL, FALSE);
05431   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05432   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05433   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05434 
05435   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05436     return FALSE;
05437 
05438   CONNECTION_LOCK (connection);
05439 
05440   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05441                                                          (const char **) decomposed_path,
05442                                                          child_entries);
05443   dbus_free_string_array (decomposed_path);
05444 
05445   return retval;
05446 }
05447 
05448 static DBusDataSlotAllocator slot_allocator;
05449 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05450 
05465 dbus_bool_t
05466 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05467 {
05468   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05469                                           &_DBUS_LOCK_NAME (connection_slots),
05470                                           slot_p);
05471 }
05472 
05484 void
05485 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05486 {
05487   _dbus_return_if_fail (*slot_p >= 0);
05488   
05489   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05490 }
05491 
05505 dbus_bool_t
05506 dbus_connection_set_data (DBusConnection   *connection,
05507                           dbus_int32_t      slot,
05508                           void             *data,
05509                           DBusFreeFunction  free_data_func)
05510 {
05511   DBusFreeFunction old_free_func;
05512   void *old_data;
05513   dbus_bool_t retval;
05514 
05515   _dbus_return_val_if_fail (connection != NULL, FALSE);
05516   _dbus_return_val_if_fail (slot >= 0, FALSE);
05517   
05518   CONNECTION_LOCK (connection);
05519 
05520   retval = _dbus_data_slot_list_set (&slot_allocator,
05521                                      &connection->slot_list,
05522                                      slot, data, free_data_func,
05523                                      &old_free_func, &old_data);
05524   
05525   CONNECTION_UNLOCK (connection);
05526 
05527   if (retval)
05528     {
05529       /* Do the actual free outside the connection lock */
05530       if (old_free_func)
05531         (* old_free_func) (old_data);
05532     }
05533 
05534   return retval;
05535 }
05536 
05545 void*
05546 dbus_connection_get_data (DBusConnection   *connection,
05547                           dbus_int32_t      slot)
05548 {
05549   void *res;
05550 
05551   _dbus_return_val_if_fail (connection != NULL, NULL);
05552   
05553   CONNECTION_LOCK (connection);
05554 
05555   res = _dbus_data_slot_list_get (&slot_allocator,
05556                                   &connection->slot_list,
05557                                   slot);
05558   
05559   CONNECTION_UNLOCK (connection);
05560 
05561   return res;
05562 }
05563 
05570 void
05571 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05572 {  
05573   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05574 }
05575 
05584 void
05585 dbus_connection_set_max_message_size (DBusConnection *connection,
05586                                       long            size)
05587 {
05588   _dbus_return_if_fail (connection != NULL);
05589   
05590   CONNECTION_LOCK (connection);
05591   _dbus_transport_set_max_message_size (connection->transport,
05592                                         size);
05593   CONNECTION_UNLOCK (connection);
05594 }
05595 
05602 long
05603 dbus_connection_get_max_message_size (DBusConnection *connection)
05604 {
05605   long res;
05606 
05607   _dbus_return_val_if_fail (connection != NULL, 0);
05608   
05609   CONNECTION_LOCK (connection);
05610   res = _dbus_transport_get_max_message_size (connection->transport);
05611   CONNECTION_UNLOCK (connection);
05612   return res;
05613 }
05614 
05640 void
05641 dbus_connection_set_max_received_size (DBusConnection *connection,
05642                                        long            size)
05643 {
05644   _dbus_return_if_fail (connection != NULL);
05645   
05646   CONNECTION_LOCK (connection);
05647   _dbus_transport_set_max_received_size (connection->transport,
05648                                          size);
05649   CONNECTION_UNLOCK (connection);
05650 }
05651 
05658 long
05659 dbus_connection_get_max_received_size (DBusConnection *connection)
05660 {
05661   long res;
05662 
05663   _dbus_return_val_if_fail (connection != NULL, 0);
05664   
05665   CONNECTION_LOCK (connection);
05666   res = _dbus_transport_get_max_received_size (connection->transport);
05667   CONNECTION_UNLOCK (connection);
05668   return res;
05669 }
05670 
05681 long
05682 dbus_connection_get_outgoing_size (DBusConnection *connection)
05683 {
05684   long res;
05685 
05686   _dbus_return_val_if_fail (connection != NULL, 0);
05687   
05688   CONNECTION_LOCK (connection);
05689   res = _dbus_counter_get_value (connection->outgoing_counter);
05690   CONNECTION_UNLOCK (connection);
05691   return res;
05692 }
05693 

Generated on Fri Oct 5 11:45:34 2007 for D-Bus by  doxygen 1.5.3