dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002-2006  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 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   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00285    * from connection->mutex and all bitfields in a word have to be read/written together.
00286    * So you can't have a different lock for different bitfields in the same word.
00287    */
00288   dbus_bool_t dispatch_acquired; 
00289   dbus_bool_t io_path_acquired;  
00291   unsigned int shareable : 1; 
00293   unsigned int exit_on_disconnect : 1; 
00295   unsigned int route_peer_messages : 1; 
00297   unsigned int disconnected_message_arrived : 1;   
00301   unsigned int disconnected_message_processed : 1; 
00305 #ifndef DBUS_DISABLE_CHECKS
00306   unsigned int have_connection_lock : 1; 
00307 #endif
00308   
00309 #ifndef DBUS_DISABLE_CHECKS
00310   int generation; 
00311 #endif 
00312 };
00313 
00314 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00315 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00316                                                                               DBusDispatchStatus  new_status);
00317 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00318 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00319 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00320 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00321 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00322 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00323 
00324 static DBusMessageFilter *
00325 _dbus_message_filter_ref (DBusMessageFilter *filter)
00326 {
00327   _dbus_assert (filter->refcount.value > 0);
00328   _dbus_atomic_inc (&filter->refcount);
00329 
00330   return filter;
00331 }
00332 
00333 static void
00334 _dbus_message_filter_unref (DBusMessageFilter *filter)
00335 {
00336   _dbus_assert (filter->refcount.value > 0);
00337 
00338   if (_dbus_atomic_dec (&filter->refcount) == 1)
00339     {
00340       if (filter->free_user_data_function)
00341         (* filter->free_user_data_function) (filter->user_data);
00342       
00343       dbus_free (filter);
00344     }
00345 }
00346 
00352 void
00353 _dbus_connection_lock (DBusConnection *connection)
00354 {
00355   CONNECTION_LOCK (connection);
00356 }
00357 
00363 void
00364 _dbus_connection_unlock (DBusConnection *connection)
00365 {
00366   CONNECTION_UNLOCK (connection);
00367 }
00368 
00376 static void
00377 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00378 {
00379   if (connection->wakeup_main_function)
00380     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00381 }
00382 
00383 #ifdef DBUS_BUILD_TESTS
00384 /* For now this function isn't used */
00394 dbus_bool_t
00395 _dbus_connection_queue_received_message (DBusConnection *connection,
00396                                          DBusMessage    *message)
00397 {
00398   DBusList *link;
00399 
00400   link = _dbus_list_alloc_link (message);
00401   if (link == NULL)
00402     return FALSE;
00403 
00404   dbus_message_ref (message);
00405   _dbus_connection_queue_received_message_link (connection, link);
00406 
00407   return TRUE;
00408 }
00409 
00422 void 
00423 _dbus_connection_test_get_locks (DBusConnection *connection,
00424                                  DBusMutex     **mutex_loc,
00425                                  DBusMutex     **dispatch_mutex_loc,
00426                                  DBusMutex     **io_path_mutex_loc,
00427                                  DBusCondVar   **dispatch_cond_loc,
00428                                  DBusCondVar   **io_path_cond_loc)
00429 {
00430   *mutex_loc = connection->mutex;
00431   *dispatch_mutex_loc = connection->dispatch_mutex;
00432   *io_path_mutex_loc = connection->io_path_mutex; 
00433   *dispatch_cond_loc = connection->dispatch_cond;
00434   *io_path_cond_loc = connection->io_path_cond;
00435 }
00436 #endif
00437 
00446 void
00447 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00448                                               DBusList        *link)
00449 {
00450   DBusPendingCall *pending;
00451   dbus_int32_t reply_serial;
00452   DBusMessage *message;
00453   
00454   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00455   
00456   _dbus_list_append_link (&connection->incoming_messages,
00457                           link);
00458   message = link->data;
00459 
00460   /* If this is a reply we're waiting on, remove timeout for it */
00461   reply_serial = dbus_message_get_reply_serial (message);
00462   if (reply_serial != -1)
00463     {
00464       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00465                                              reply_serial);
00466       if (pending != NULL)
00467         {
00468           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00469             _dbus_connection_remove_timeout_unlocked (connection,
00470                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00471 
00472           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00473         }
00474     }
00475   
00476   
00477 
00478   connection->n_incoming += 1;
00479 
00480   _dbus_connection_wakeup_mainloop (connection);
00481   
00482   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00483                  message,
00484                  dbus_message_get_type (message),
00485                  dbus_message_get_path (message) ?
00486                  dbus_message_get_path (message) :
00487                  "no path",
00488                  dbus_message_get_interface (message) ?
00489                  dbus_message_get_interface (message) :
00490                  "no interface",
00491                  dbus_message_get_member (message) ?
00492                  dbus_message_get_member (message) :
00493                  "no member",
00494                  dbus_message_get_signature (message),
00495                  dbus_message_get_reply_serial (message),
00496                  connection,
00497                  connection->n_incoming);}
00498 
00507 void
00508 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00509                                                  DBusList *link)
00510 {
00511   HAVE_LOCK_CHECK (connection);
00512   
00513   _dbus_list_append_link (&connection->incoming_messages, link);
00514 
00515   connection->n_incoming += 1;
00516 
00517   _dbus_connection_wakeup_mainloop (connection);
00518   
00519   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00520                  link->data, connection, connection->n_incoming);
00521 }
00522 
00523 
00531 dbus_bool_t
00532 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00533 {
00534   HAVE_LOCK_CHECK (connection);
00535   return connection->outgoing_messages != NULL;
00536 }
00537 
00547 dbus_bool_t
00548 dbus_connection_has_messages_to_send (DBusConnection *connection)
00549 {
00550   dbus_bool_t v;
00551   
00552   _dbus_return_val_if_fail (connection != NULL, FALSE);
00553 
00554   CONNECTION_LOCK (connection);
00555   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00556   CONNECTION_UNLOCK (connection);
00557 
00558   return v;
00559 }
00560 
00568 DBusMessage*
00569 _dbus_connection_get_message_to_send (DBusConnection *connection)
00570 {
00571   HAVE_LOCK_CHECK (connection);
00572   
00573   return _dbus_list_get_last (&connection->outgoing_messages);
00574 }
00575 
00584 void
00585 _dbus_connection_message_sent (DBusConnection *connection,
00586                                DBusMessage    *message)
00587 {
00588   DBusList *link;
00589 
00590   HAVE_LOCK_CHECK (connection);
00591   
00592   /* This can be called before we even complete authentication, since
00593    * it's called on disconnect to clean up the outgoing queue.
00594    * It's also called as we successfully send each message.
00595    */
00596   
00597   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00598   _dbus_assert (link != NULL);
00599   _dbus_assert (link->data == message);
00600 
00601   /* Save this link in the link cache */
00602   _dbus_list_unlink (&connection->outgoing_messages,
00603                      link);
00604   _dbus_list_prepend_link (&connection->link_cache, link);
00605   
00606   connection->n_outgoing -= 1;
00607 
00608   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00609                  message,
00610                  dbus_message_get_type (message),
00611                  dbus_message_get_path (message) ?
00612                  dbus_message_get_path (message) :
00613                  "no path",
00614                  dbus_message_get_interface (message) ?
00615                  dbus_message_get_interface (message) :
00616                  "no interface",
00617                  dbus_message_get_member (message) ?
00618                  dbus_message_get_member (message) :
00619                  "no member",
00620                  dbus_message_get_signature (message),
00621                  connection, connection->n_outgoing);
00622 
00623   /* Save this link in the link cache also */
00624   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00625                                      &link);
00626   _dbus_list_prepend_link (&connection->link_cache, link);
00627   
00628   dbus_message_unref (message);
00629 }
00630 
00632 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00633                                                   DBusWatch     *watch);
00635 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00636                                                   DBusWatch     *watch);
00638 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00639                                                   DBusWatch     *watch,
00640                                                   dbus_bool_t    enabled);
00641 
00642 static dbus_bool_t
00643 protected_change_watch (DBusConnection         *connection,
00644                         DBusWatch              *watch,
00645                         DBusWatchAddFunction    add_function,
00646                         DBusWatchRemoveFunction remove_function,
00647                         DBusWatchToggleFunction toggle_function,
00648                         dbus_bool_t             enabled)
00649 {
00650   DBusWatchList *watches;
00651   dbus_bool_t retval;
00652   
00653   HAVE_LOCK_CHECK (connection);
00654 
00655   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00656    * drop lock and call out" one; but it has to be propagated up through all callers
00657    */
00658   
00659   watches = connection->watches;
00660   if (watches)
00661     {
00662       connection->watches = NULL;
00663       _dbus_connection_ref_unlocked (connection);
00664       CONNECTION_UNLOCK (connection);
00665 
00666       if (add_function)
00667         retval = (* add_function) (watches, watch);
00668       else if (remove_function)
00669         {
00670           retval = TRUE;
00671           (* remove_function) (watches, watch);
00672         }
00673       else
00674         {
00675           retval = TRUE;
00676           (* toggle_function) (watches, watch, enabled);
00677         }
00678       
00679       CONNECTION_LOCK (connection);
00680       connection->watches = watches;
00681       _dbus_connection_unref_unlocked (connection);
00682 
00683       return retval;
00684     }
00685   else
00686     return FALSE;
00687 }
00688      
00689 
00701 dbus_bool_t
00702 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00703                                      DBusWatch      *watch)
00704 {
00705   return protected_change_watch (connection, watch,
00706                                  _dbus_watch_list_add_watch,
00707                                  NULL, NULL, FALSE);
00708 }
00709 
00719 void
00720 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00721                                         DBusWatch      *watch)
00722 {
00723   protected_change_watch (connection, watch,
00724                           NULL,
00725                           _dbus_watch_list_remove_watch,
00726                           NULL, FALSE);
00727 }
00728 
00739 void
00740 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00741                                         DBusWatch      *watch,
00742                                         dbus_bool_t     enabled)
00743 {
00744   _dbus_assert (watch != NULL);
00745 
00746   protected_change_watch (connection, watch,
00747                           NULL, NULL,
00748                           _dbus_watch_list_toggle_watch,
00749                           enabled);
00750 }
00751 
00753 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00754                                                    DBusTimeout     *timeout);
00756 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00757                                                    DBusTimeout     *timeout);
00759 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00760                                                    DBusTimeout     *timeout,
00761                                                    dbus_bool_t      enabled);
00762 
00763 static dbus_bool_t
00764 protected_change_timeout (DBusConnection           *connection,
00765                           DBusTimeout              *timeout,
00766                           DBusTimeoutAddFunction    add_function,
00767                           DBusTimeoutRemoveFunction remove_function,
00768                           DBusTimeoutToggleFunction toggle_function,
00769                           dbus_bool_t               enabled)
00770 {
00771   DBusTimeoutList *timeouts;
00772   dbus_bool_t retval;
00773   
00774   HAVE_LOCK_CHECK (connection);
00775 
00776   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00777    * drop lock and call out" one; but it has to be propagated up through all callers
00778    */
00779   
00780   timeouts = connection->timeouts;
00781   if (timeouts)
00782     {
00783       connection->timeouts = NULL;
00784       _dbus_connection_ref_unlocked (connection);
00785       CONNECTION_UNLOCK (connection);
00786 
00787       if (add_function)
00788         retval = (* add_function) (timeouts, timeout);
00789       else if (remove_function)
00790         {
00791           retval = TRUE;
00792           (* remove_function) (timeouts, timeout);
00793         }
00794       else
00795         {
00796           retval = TRUE;
00797           (* toggle_function) (timeouts, timeout, enabled);
00798         }
00799       
00800       CONNECTION_LOCK (connection);
00801       connection->timeouts = timeouts;
00802       _dbus_connection_unref_unlocked (connection);
00803 
00804       return retval;
00805     }
00806   else
00807     return FALSE;
00808 }
00809 
00822 dbus_bool_t
00823 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00824                                        DBusTimeout    *timeout)
00825 {
00826   return protected_change_timeout (connection, timeout,
00827                                    _dbus_timeout_list_add_timeout,
00828                                    NULL, NULL, FALSE);
00829 }
00830 
00840 void
00841 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00842                                           DBusTimeout    *timeout)
00843 {
00844   protected_change_timeout (connection, timeout,
00845                             NULL,
00846                             _dbus_timeout_list_remove_timeout,
00847                             NULL, FALSE);
00848 }
00849 
00860 void
00861 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00862                                           DBusTimeout      *timeout,
00863                                           dbus_bool_t       enabled)
00864 {
00865   protected_change_timeout (connection, timeout,
00866                             NULL, NULL,
00867                             _dbus_timeout_list_toggle_timeout,
00868                             enabled);
00869 }
00870 
00871 static dbus_bool_t
00872 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00873                                                DBusPendingCall *pending)
00874 {
00875   dbus_uint32_t reply_serial;
00876   DBusTimeout *timeout;
00877 
00878   HAVE_LOCK_CHECK (connection);
00879 
00880   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00881 
00882   _dbus_assert (reply_serial != 0);
00883 
00884   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00885 
00886   if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00887     return FALSE;
00888   
00889   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00890                                     reply_serial,
00891                                     pending))
00892     {
00893       _dbus_connection_remove_timeout_unlocked (connection, timeout);
00894 
00895       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00896       HAVE_LOCK_CHECK (connection);
00897       return FALSE;
00898     }
00899   
00900   _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00901 
00902   _dbus_pending_call_ref_unlocked (pending);
00903 
00904   HAVE_LOCK_CHECK (connection);
00905   
00906   return TRUE;
00907 }
00908 
00909 static void
00910 free_pending_call_on_hash_removal (void *data)
00911 {
00912   DBusPendingCall *pending;
00913   DBusConnection  *connection;
00914   
00915   if (data == NULL)
00916     return;
00917 
00918   pending = data;
00919 
00920   connection = _dbus_pending_call_get_connection_unlocked (pending);
00921 
00922   HAVE_LOCK_CHECK (connection);
00923   
00924   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00925     {
00926       _dbus_connection_remove_timeout_unlocked (connection,
00927                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00928       
00929       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00930     }
00931 
00932   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00933    * here, but the pending call finalizer could in principle call out to 
00934    * application code so we pretty much have to... some larger code reorg 
00935    * might be needed.
00936    */
00937   _dbus_connection_ref_unlocked (connection);
00938   _dbus_pending_call_unref_and_unlock (pending);
00939   CONNECTION_LOCK (connection);
00940   _dbus_connection_unref_unlocked (connection);
00941 }
00942 
00943 static void
00944 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00945                                                DBusPendingCall *pending)
00946 {
00947   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00948    * say the least.
00949    */
00950   _dbus_hash_table_remove_int (connection->pending_replies,
00951                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00952 }
00953 
00954 static void
00955 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00956                                                  DBusPendingCall *pending)
00957 {
00958   /* The idea here is to avoid finalizing the pending call
00959    * with the lock held, since there's a destroy notifier
00960    * in pending call that goes out to application code.
00961    *
00962    * There's an extra unlock inside the hash table
00963    * "free pending call" function FIXME...
00964    */
00965   _dbus_pending_call_ref_unlocked (pending);
00966   _dbus_hash_table_remove_int (connection->pending_replies,
00967                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00968   _dbus_pending_call_unref_and_unlock (pending);
00969 }
00970 
00979 void
00980 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00981                                       DBusPendingCall *pending)
00982 {
00983   CONNECTION_LOCK (connection);
00984   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00985 }
00986 
00996 static dbus_bool_t
00997 _dbus_connection_acquire_io_path (DBusConnection *connection,
00998                                   int             timeout_milliseconds)
00999 {
01000   dbus_bool_t we_acquired;
01001   
01002   HAVE_LOCK_CHECK (connection);
01003 
01004   /* We don't want the connection to vanish */
01005   _dbus_connection_ref_unlocked (connection);
01006 
01007   /* We will only touch io_path_acquired which is protected by our mutex */
01008   CONNECTION_UNLOCK (connection);
01009   
01010   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01011   _dbus_mutex_lock (connection->io_path_mutex);
01012 
01013   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01014                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01015 
01016   we_acquired = FALSE;
01017   
01018   if (connection->io_path_acquired)
01019     {
01020       if (timeout_milliseconds != -1)
01021         {
01022           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01023                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
01024 
01025           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01026                                            connection->io_path_mutex,
01027                                            timeout_milliseconds))
01028             {
01029               /* We timed out before anyone signaled. */
01030               /* (writing the loop to handle the !timedout case by
01031                * waiting longer if needed is a pain since dbus
01032                * wraps pthread_cond_timedwait to take a relative
01033                * time instead of absolute, something kind of stupid
01034                * on our part. for now it doesn't matter, we will just
01035                * end up back here eventually.)
01036                */
01037             }
01038         }
01039       else
01040         {
01041           while (connection->io_path_acquired)
01042             {
01043               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01044               _dbus_condvar_wait (connection->io_path_cond, 
01045                                   connection->io_path_mutex);
01046             }
01047         }
01048     }
01049   
01050   if (!connection->io_path_acquired)
01051     {
01052       we_acquired = TRUE;
01053       connection->io_path_acquired = TRUE;
01054     }
01055   
01056   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01057                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01058 
01059   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01060   _dbus_mutex_unlock (connection->io_path_mutex);
01061 
01062   CONNECTION_LOCK (connection);
01063   
01064   HAVE_LOCK_CHECK (connection);
01065 
01066   _dbus_connection_unref_unlocked (connection);
01067   
01068   return we_acquired;
01069 }
01070 
01078 static void
01079 _dbus_connection_release_io_path (DBusConnection *connection)
01080 {
01081   HAVE_LOCK_CHECK (connection);
01082   
01083   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01084   _dbus_mutex_lock (connection->io_path_mutex);
01085   
01086   _dbus_assert (connection->io_path_acquired);
01087 
01088   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01089                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01090   
01091   connection->io_path_acquired = FALSE;
01092   _dbus_condvar_wake_one (connection->io_path_cond);
01093 
01094   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01095   _dbus_mutex_unlock (connection->io_path_mutex);
01096 }
01097 
01126 void
01127 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01128                                         unsigned int    flags,
01129                                         int             timeout_milliseconds)
01130 {
01131   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01132   
01133   HAVE_LOCK_CHECK (connection);
01134   
01135   if (connection->n_outgoing == 0)
01136     flags &= ~DBUS_ITERATION_DO_WRITING;
01137 
01138   if (_dbus_connection_acquire_io_path (connection,
01139                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01140     {
01141       HAVE_LOCK_CHECK (connection);
01142       
01143       _dbus_transport_do_iteration (connection->transport,
01144                                     flags, timeout_milliseconds);
01145       _dbus_connection_release_io_path (connection);
01146     }
01147 
01148   HAVE_LOCK_CHECK (connection);
01149 
01150   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01151 }
01152 
01162 DBusConnection*
01163 _dbus_connection_new_for_transport (DBusTransport *transport)
01164 {
01165   DBusConnection *connection;
01166   DBusWatchList *watch_list;
01167   DBusTimeoutList *timeout_list;
01168   DBusHashTable *pending_replies;
01169   DBusList *disconnect_link;
01170   DBusMessage *disconnect_message;
01171   DBusCounter *outgoing_counter;
01172   DBusObjectTree *objects;
01173   
01174   watch_list = NULL;
01175   connection = NULL;
01176   pending_replies = NULL;
01177   timeout_list = NULL;
01178   disconnect_link = NULL;
01179   disconnect_message = NULL;
01180   outgoing_counter = NULL;
01181   objects = NULL;
01182   
01183   watch_list = _dbus_watch_list_new ();
01184   if (watch_list == NULL)
01185     goto error;
01186 
01187   timeout_list = _dbus_timeout_list_new ();
01188   if (timeout_list == NULL)
01189     goto error;  
01190 
01191   pending_replies =
01192     _dbus_hash_table_new (DBUS_HASH_INT,
01193                           NULL,
01194                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01195   if (pending_replies == NULL)
01196     goto error;
01197   
01198   connection = dbus_new0 (DBusConnection, 1);
01199   if (connection == NULL)
01200     goto error;
01201 
01202   _dbus_mutex_new_at_location (&connection->mutex);
01203   if (connection->mutex == NULL)
01204     goto error;
01205 
01206   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01207   if (connection->io_path_mutex == NULL)
01208     goto error;
01209 
01210   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01211   if (connection->dispatch_mutex == NULL)
01212     goto error;
01213   
01214   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01215   if (connection->dispatch_cond == NULL)
01216     goto error;
01217   
01218   _dbus_condvar_new_at_location (&connection->io_path_cond);
01219   if (connection->io_path_cond == NULL)
01220     goto error;
01221 
01222   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01223                                                 DBUS_INTERFACE_LOCAL,
01224                                                 "Disconnected");
01225   
01226   if (disconnect_message == NULL)
01227     goto error;
01228 
01229   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01230   if (disconnect_link == NULL)
01231     goto error;
01232 
01233   outgoing_counter = _dbus_counter_new ();
01234   if (outgoing_counter == NULL)
01235     goto error;
01236 
01237   objects = _dbus_object_tree_new (connection);
01238   if (objects == NULL)
01239     goto error;
01240   
01241   if (_dbus_modify_sigpipe)
01242     _dbus_disable_sigpipe ();
01243   
01244   connection->refcount.value = 1;
01245   connection->transport = transport;
01246   connection->watches = watch_list;
01247   connection->timeouts = timeout_list;
01248   connection->pending_replies = pending_replies;
01249   connection->outgoing_counter = outgoing_counter;
01250   connection->filter_list = NULL;
01251   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01252   connection->objects = objects;
01253   connection->exit_on_disconnect = FALSE;
01254   connection->shareable = FALSE;
01255   connection->route_peer_messages = FALSE;
01256   connection->disconnected_message_arrived = FALSE;
01257   connection->disconnected_message_processed = FALSE;
01258   
01259 #ifndef DBUS_DISABLE_CHECKS
01260   connection->generation = _dbus_current_generation;
01261 #endif
01262   
01263   _dbus_data_slot_list_init (&connection->slot_list);
01264 
01265   connection->client_serial = 1;
01266 
01267   connection->disconnect_message_link = disconnect_link;
01268 
01269   CONNECTION_LOCK (connection);
01270   
01271   if (!_dbus_transport_set_connection (transport, connection))
01272     {
01273       CONNECTION_UNLOCK (connection);
01274 
01275       goto error;
01276     }
01277 
01278   _dbus_transport_ref (transport);
01279 
01280   CONNECTION_UNLOCK (connection);
01281   
01282   return connection;
01283   
01284  error:
01285   if (disconnect_message != NULL)
01286     dbus_message_unref (disconnect_message);
01287   
01288   if (disconnect_link != NULL)
01289     _dbus_list_free_link (disconnect_link);
01290   
01291   if (connection != NULL)
01292     {
01293       _dbus_condvar_free_at_location (&connection->io_path_cond);
01294       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01295       _dbus_mutex_free_at_location (&connection->mutex);
01296       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01297       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01298       dbus_free (connection);
01299     }
01300   if (pending_replies)
01301     _dbus_hash_table_unref (pending_replies);
01302   
01303   if (watch_list)
01304     _dbus_watch_list_free (watch_list);
01305 
01306   if (timeout_list)
01307     _dbus_timeout_list_free (timeout_list);
01308 
01309   if (outgoing_counter)
01310     _dbus_counter_unref (outgoing_counter);
01311 
01312   if (objects)
01313     _dbus_object_tree_unref (objects);
01314   
01315   return NULL;
01316 }
01317 
01325 DBusConnection *
01326 _dbus_connection_ref_unlocked (DBusConnection *connection)
01327 {  
01328   _dbus_assert (connection != NULL);
01329   _dbus_assert (connection->generation == _dbus_current_generation);
01330 
01331   HAVE_LOCK_CHECK (connection);
01332   
01333 #ifdef DBUS_HAVE_ATOMIC_INT
01334   _dbus_atomic_inc (&connection->refcount);
01335 #else
01336   _dbus_assert (connection->refcount.value > 0);
01337   connection->refcount.value += 1;
01338 #endif
01339 
01340   return connection;
01341 }
01342 
01349 void
01350 _dbus_connection_unref_unlocked (DBusConnection *connection)
01351 {
01352   dbus_bool_t last_unref;
01353 
01354   HAVE_LOCK_CHECK (connection);
01355   
01356   _dbus_assert (connection != NULL);
01357 
01358   /* The connection lock is better than the global
01359    * lock in the atomic increment fallback
01360    */
01361   
01362 #ifdef DBUS_HAVE_ATOMIC_INT
01363   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01364 #else
01365   _dbus_assert (connection->refcount.value > 0);
01366 
01367   connection->refcount.value -= 1;
01368   last_unref = (connection->refcount.value == 0);  
01369 #if 0
01370   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01371 #endif
01372 #endif
01373   
01374   if (last_unref)
01375     _dbus_connection_last_unref (connection);
01376 }
01377 
01378 static dbus_uint32_t
01379 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01380 {
01381   dbus_uint32_t serial;
01382 
01383   serial = connection->client_serial++;
01384 
01385   if (connection->client_serial == 0)
01386     connection->client_serial = 1;
01387 
01388   return serial;
01389 }
01390 
01404 dbus_bool_t
01405 _dbus_connection_handle_watch (DBusWatch                   *watch,
01406                                unsigned int                 condition,
01407                                void                        *data)
01408 {
01409   DBusConnection *connection;
01410   dbus_bool_t retval;
01411   DBusDispatchStatus status;
01412 
01413   connection = data;
01414 
01415   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01416   
01417   CONNECTION_LOCK (connection);
01418   _dbus_connection_acquire_io_path (connection, -1);
01419   HAVE_LOCK_CHECK (connection);
01420   retval = _dbus_transport_handle_watch (connection->transport,
01421                                          watch, condition);
01422 
01423   _dbus_connection_release_io_path (connection);
01424 
01425   HAVE_LOCK_CHECK (connection);
01426 
01427   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01428   
01429   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01430 
01431   /* this calls out to user code */
01432   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01433 
01434   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01435   
01436   return retval;
01437 }
01438 
01439 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01440 static DBusHashTable *shared_connections = NULL;
01441 static DBusList *shared_connections_no_guid = NULL;
01442 
01443 static void
01444 close_connection_on_shutdown (DBusConnection *connection)
01445 {
01446   DBusMessage *message;
01447 
01448   dbus_connection_ref (connection);
01449   _dbus_connection_close_possibly_shared (connection);
01450 
01451   /* Churn through to the Disconnected message */
01452   while ((message = dbus_connection_pop_message (connection)))
01453     {
01454       dbus_message_unref (message);
01455     }
01456   dbus_connection_unref (connection);
01457 }
01458 
01459 static void
01460 shared_connections_shutdown (void *data)
01461 {
01462   int n_entries;
01463   
01464   _DBUS_LOCK (shared_connections);
01465   
01466   /* This is a little bit unpleasant... better ideas? */
01467   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01468     {
01469       DBusConnection *connection;
01470       DBusHashIter iter;
01471       
01472       _dbus_hash_iter_init (shared_connections, &iter);
01473       _dbus_hash_iter_next (&iter);
01474        
01475       connection = _dbus_hash_iter_get_value (&iter);
01476 
01477       _DBUS_UNLOCK (shared_connections);
01478       close_connection_on_shutdown (connection);
01479       _DBUS_LOCK (shared_connections);
01480 
01481       /* The connection should now be dead and not in our hash ... */
01482       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01483     }
01484 
01485   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01486   
01487   _dbus_hash_table_unref (shared_connections);
01488   shared_connections = NULL;
01489 
01490   if (shared_connections_no_guid != NULL)
01491     {
01492       DBusConnection *connection;
01493       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01494       while (connection != NULL)
01495         {
01496           _DBUS_UNLOCK (shared_connections);
01497           close_connection_on_shutdown (connection);
01498           _DBUS_LOCK (shared_connections);
01499           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01500         }
01501     }
01502 
01503   shared_connections_no_guid = NULL;
01504   
01505   _DBUS_UNLOCK (shared_connections);
01506 }
01507 
01508 static dbus_bool_t
01509 connection_lookup_shared (DBusAddressEntry  *entry,
01510                           DBusConnection   **result)
01511 {
01512   _dbus_verbose ("checking for existing connection\n");
01513   
01514   *result = NULL;
01515   
01516   _DBUS_LOCK (shared_connections);
01517 
01518   if (shared_connections == NULL)
01519     {
01520       _dbus_verbose ("creating shared_connections hash table\n");
01521       
01522       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01523                                                  dbus_free,
01524                                                  NULL);
01525       if (shared_connections == NULL)
01526         {
01527           _DBUS_UNLOCK (shared_connections);
01528           return FALSE;
01529         }
01530 
01531       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01532         {
01533           _dbus_hash_table_unref (shared_connections);
01534           shared_connections = NULL;
01535           _DBUS_UNLOCK (shared_connections);
01536           return FALSE;
01537         }
01538 
01539       _dbus_verbose ("  successfully created shared_connections\n");
01540       
01541       _DBUS_UNLOCK (shared_connections);
01542       return TRUE; /* no point looking up in the hash we just made */
01543     }
01544   else
01545     {
01546       const char *guid;
01547 
01548       guid = dbus_address_entry_get_value (entry, "guid");
01549       
01550       if (guid != NULL)
01551         {
01552           DBusConnection *connection;
01553           
01554           connection = _dbus_hash_table_lookup_string (shared_connections,
01555                                                        guid);
01556 
01557           if (connection)
01558             {
01559               /* The DBusConnection can't be finalized without taking
01560                * the shared_connections lock to remove it from the
01561                * hash.  So it's safe to ref the connection here.
01562                * However, it may be disconnected if the Disconnected
01563                * message hasn't been processed yet, in which case we
01564                * want to pretend it isn't in the hash and avoid
01565                * returning it.
01566                *
01567                * The idea is to avoid ever returning a disconnected connection
01568                * from dbus_connection_open(). We could just synchronously
01569                * drop our shared ref to the connection on connection disconnect,
01570                * and then assert here that the connection is connected, but
01571                * that causes reentrancy headaches.
01572                */
01573               CONNECTION_LOCK (connection);
01574               if (_dbus_connection_get_is_connected_unlocked (connection))
01575                 {
01576                   _dbus_connection_ref_unlocked (connection);
01577                   *result = connection;
01578                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01579                                  guid);
01580                 }
01581               else
01582                 {
01583                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01584                                  guid);
01585                 }
01586               CONNECTION_UNLOCK (connection);
01587             }
01588         }
01589       
01590       _DBUS_UNLOCK (shared_connections);
01591       return TRUE;
01592     }
01593 }
01594 
01595 static dbus_bool_t
01596 connection_record_shared_unlocked (DBusConnection *connection,
01597                                    const char     *guid)
01598 {
01599   char *guid_key;
01600   char *guid_in_connection;
01601 
01602   HAVE_LOCK_CHECK (connection);
01603   _dbus_assert (connection->server_guid == NULL);
01604   _dbus_assert (connection->shareable);
01605 
01606   /* get a hard ref on this connection, even if
01607    * we won't in fact store it in the hash, we still
01608    * need to hold a ref on it until it's disconnected.
01609    */
01610   _dbus_connection_ref_unlocked (connection);
01611 
01612   if (guid == NULL)
01613     {
01614       _DBUS_LOCK (shared_connections);
01615 
01616       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01617         {
01618           _DBUS_UNLOCK (shared_connections);
01619           return FALSE;
01620         }
01621 
01622       _DBUS_UNLOCK (shared_connections);
01623       return TRUE; /* don't store in the hash */
01624     }
01625   
01626   /* A separate copy of the key is required in the hash table, because
01627    * we don't have a lock on the connection when we are doing a hash
01628    * lookup.
01629    */
01630   
01631   guid_key = _dbus_strdup (guid);
01632   if (guid_key == NULL)
01633     return FALSE;
01634 
01635   guid_in_connection = _dbus_strdup (guid);
01636   if (guid_in_connection == NULL)
01637     {
01638       dbus_free (guid_key);
01639       return FALSE;
01640     }
01641   
01642   _DBUS_LOCK (shared_connections);
01643   _dbus_assert (shared_connections != NULL);
01644   
01645   if (!_dbus_hash_table_insert_string (shared_connections,
01646                                        guid_key, connection))
01647     {
01648       dbus_free (guid_key);
01649       dbus_free (guid_in_connection);
01650       _DBUS_UNLOCK (shared_connections);
01651       return FALSE;
01652     }
01653 
01654   connection->server_guid = guid_in_connection;
01655 
01656   _dbus_verbose ("stored connection to %s to be shared\n",
01657                  connection->server_guid);
01658   
01659   _DBUS_UNLOCK (shared_connections);
01660 
01661   _dbus_assert (connection->server_guid != NULL);
01662   
01663   return TRUE;
01664 }
01665 
01666 static void
01667 connection_forget_shared_unlocked (DBusConnection *connection)
01668 {
01669   HAVE_LOCK_CHECK (connection);
01670 
01671   if (!connection->shareable)
01672     return;
01673   
01674   if (connection->server_guid != NULL)
01675     {
01676       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01677                      connection->server_guid);
01678       
01679       _DBUS_LOCK (shared_connections);
01680       
01681       if (!_dbus_hash_table_remove_string (shared_connections,
01682                                            connection->server_guid))
01683         _dbus_assert_not_reached ("connection was not in the shared table");
01684       
01685       dbus_free (connection->server_guid);
01686       connection->server_guid = NULL;
01687       _DBUS_UNLOCK (shared_connections);
01688     }
01689   
01690   /* remove our reference held on all shareable connections */
01691   _dbus_connection_unref_unlocked (connection);
01692 }
01693 
01694 static DBusConnection*
01695 connection_try_from_address_entry (DBusAddressEntry *entry,
01696                                    DBusError        *error)
01697 {
01698   DBusTransport *transport;
01699   DBusConnection *connection;
01700 
01701   transport = _dbus_transport_open (entry, error);
01702 
01703   if (transport == NULL)
01704     {
01705       _DBUS_ASSERT_ERROR_IS_SET (error);
01706       return NULL;
01707     }
01708 
01709   connection = _dbus_connection_new_for_transport (transport);
01710 
01711   _dbus_transport_unref (transport);
01712   
01713   if (connection == NULL)
01714     {
01715       _DBUS_SET_OOM (error);
01716       return NULL;
01717     }
01718 
01719 #ifndef DBUS_DISABLE_CHECKS
01720   _dbus_assert (!connection->have_connection_lock);
01721 #endif
01722   return connection;
01723 }
01724 
01725 /*
01726  * If the shared parameter is true, then any existing connection will
01727  * be used (and if a new connection is created, it will be available
01728  * for use by others). If the shared parameter is false, a new
01729  * connection will always be created, and the new connection will
01730  * never be returned to other callers.
01731  *
01732  * @param address the address
01733  * @param shared whether the connection is shared or private
01734  * @param error error return
01735  * @returns the connection or #NULL on error
01736  */
01737 static DBusConnection*
01738 _dbus_connection_open_internal (const char     *address,
01739                                 dbus_bool_t     shared,
01740                                 DBusError      *error)
01741 {
01742   DBusConnection *connection;
01743   DBusAddressEntry **entries;
01744   DBusError tmp_error = DBUS_ERROR_INIT;
01745   DBusError first_error = DBUS_ERROR_INIT;
01746   int len, i;
01747 
01748   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01749 
01750   _dbus_verbose ("opening %s connection to: %s\n",
01751                  shared ? "shared" : "private", address);
01752   
01753   if (!dbus_parse_address (address, &entries, &len, error))
01754     return NULL;
01755 
01756   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01757   
01758   connection = NULL;
01759 
01760   for (i = 0; i < len; i++)
01761     {
01762       if (shared)
01763         {
01764           if (!connection_lookup_shared (entries[i], &connection))
01765             _DBUS_SET_OOM (&tmp_error);
01766         }
01767 
01768       if (connection == NULL)
01769         {
01770           connection = connection_try_from_address_entry (entries[i],
01771                                                           &tmp_error);
01772 
01773           if (connection != NULL && shared)
01774             {
01775               const char *guid;
01776                   
01777               connection->shareable = TRUE;
01778                   
01779               /* guid may be NULL */
01780               guid = dbus_address_entry_get_value (entries[i], "guid");
01781                   
01782               CONNECTION_LOCK (connection);
01783           
01784               if (!connection_record_shared_unlocked (connection, guid))
01785                 {
01786                   _DBUS_SET_OOM (&tmp_error);
01787                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01788                   dbus_connection_unref (connection);
01789                   connection = NULL;
01790                 }
01791               else
01792                 CONNECTION_UNLOCK (connection);
01793             }
01794         }
01795       
01796       if (connection)
01797         break;
01798 
01799       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01800       
01801       if (i == 0)
01802         dbus_move_error (&tmp_error, &first_error);
01803       else
01804         dbus_error_free (&tmp_error);
01805     }
01806   
01807   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01808   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01809   
01810   if (connection == NULL)
01811     {
01812       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01813       dbus_move_error (&first_error, error);
01814     }
01815   else
01816     dbus_error_free (&first_error);
01817   
01818   dbus_address_entries_free (entries);
01819   return connection;
01820 }
01821 
01830 void
01831 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01832 {
01833   _dbus_assert (connection != NULL);
01834   _dbus_assert (connection->generation == _dbus_current_generation);
01835 
01836   CONNECTION_LOCK (connection);
01837   _dbus_connection_close_possibly_shared_and_unlock (connection);
01838 }
01839 
01840 static DBusPreallocatedSend*
01841 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01842 {
01843   DBusPreallocatedSend *preallocated;
01844 
01845   HAVE_LOCK_CHECK (connection);
01846   
01847   _dbus_assert (connection != NULL);
01848   
01849   preallocated = dbus_new (DBusPreallocatedSend, 1);
01850   if (preallocated == NULL)
01851     return NULL;
01852 
01853   if (connection->link_cache != NULL)
01854     {
01855       preallocated->queue_link =
01856         _dbus_list_pop_first_link (&connection->link_cache);
01857       preallocated->queue_link->data = NULL;
01858     }
01859   else
01860     {
01861       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01862       if (preallocated->queue_link == NULL)
01863         goto failed_0;
01864     }
01865   
01866   if (connection->link_cache != NULL)
01867     {
01868       preallocated->counter_link =
01869         _dbus_list_pop_first_link (&connection->link_cache);
01870       preallocated->counter_link->data = connection->outgoing_counter;
01871     }
01872   else
01873     {
01874       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01875       if (preallocated->counter_link == NULL)
01876         goto failed_1;
01877     }
01878 
01879   _dbus_counter_ref (preallocated->counter_link->data);
01880 
01881   preallocated->connection = connection;
01882   
01883   return preallocated;
01884   
01885  failed_1:
01886   _dbus_list_free_link (preallocated->queue_link);
01887  failed_0:
01888   dbus_free (preallocated);
01889   
01890   return NULL;
01891 }
01892 
01893 /* Called with lock held, does not update dispatch status */
01894 static void
01895 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01896                                                        DBusPreallocatedSend *preallocated,
01897                                                        DBusMessage          *message,
01898                                                        dbus_uint32_t        *client_serial)
01899 {
01900   dbus_uint32_t serial;
01901   const char *sig;
01902 
01903   preallocated->queue_link->data = message;
01904   _dbus_list_prepend_link (&connection->outgoing_messages,
01905                            preallocated->queue_link);
01906 
01907   _dbus_message_add_size_counter_link (message,
01908                                        preallocated->counter_link);
01909 
01910   dbus_free (preallocated);
01911   preallocated = NULL;
01912   
01913   dbus_message_ref (message);
01914   
01915   connection->n_outgoing += 1;
01916 
01917   sig = dbus_message_get_signature (message);
01918   
01919   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01920                  message,
01921                  dbus_message_get_type (message),
01922                  dbus_message_get_path (message) ?
01923                  dbus_message_get_path (message) :
01924                  "no path",
01925                  dbus_message_get_interface (message) ?
01926                  dbus_message_get_interface (message) :
01927                  "no interface",
01928                  dbus_message_get_member (message) ?
01929                  dbus_message_get_member (message) :
01930                  "no member",
01931                  sig,
01932                  dbus_message_get_destination (message) ?
01933                  dbus_message_get_destination (message) :
01934                  "null",
01935                  connection,
01936                  connection->n_outgoing);
01937 
01938   if (dbus_message_get_serial (message) == 0)
01939     {
01940       serial = _dbus_connection_get_next_client_serial (connection);
01941       _dbus_message_set_serial (message, serial);
01942       if (client_serial)
01943         *client_serial = serial;
01944     }
01945   else
01946     {
01947       if (client_serial)
01948         *client_serial = dbus_message_get_serial (message);
01949     }
01950 
01951   _dbus_verbose ("Message %p serial is %u\n",
01952                  message, dbus_message_get_serial (message));
01953   
01954   _dbus_message_lock (message);
01955 
01956   /* Now we need to run an iteration to hopefully just write the messages
01957    * out immediately, and otherwise get them queued up
01958    */
01959   _dbus_connection_do_iteration_unlocked (connection,
01960                                           DBUS_ITERATION_DO_WRITING,
01961                                           -1);
01962 
01963   /* If stuff is still queued up, be sure we wake up the main loop */
01964   if (connection->n_outgoing > 0)
01965     _dbus_connection_wakeup_mainloop (connection);
01966 }
01967 
01968 static void
01969 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
01970                                                DBusPreallocatedSend *preallocated,
01971                                                DBusMessage          *message,
01972                                                dbus_uint32_t        *client_serial)
01973 {
01974   DBusDispatchStatus status;
01975 
01976   HAVE_LOCK_CHECK (connection);
01977   
01978   _dbus_connection_send_preallocated_unlocked_no_update (connection,
01979                                                          preallocated,
01980                                                          message, client_serial);
01981 
01982   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01983   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01984 
01985   /* this calls out to user code */
01986   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01987 }
01988 
01998 dbus_bool_t
01999 _dbus_connection_send_and_unlock (DBusConnection *connection,
02000                                   DBusMessage    *message,
02001                                   dbus_uint32_t  *client_serial)
02002 {
02003   DBusPreallocatedSend *preallocated;
02004 
02005   _dbus_assert (connection != NULL);
02006   _dbus_assert (message != NULL);
02007   
02008   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02009   if (preallocated == NULL)
02010     {
02011       CONNECTION_UNLOCK (connection);
02012       return FALSE;
02013     }
02014 
02015   _dbus_connection_send_preallocated_and_unlock (connection,
02016                                                  preallocated,
02017                                                  message,
02018                                                  client_serial);
02019   return TRUE;
02020 }
02021 
02046 void
02047 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02048 {
02049   CONNECTION_LOCK (connection);
02050   
02051   _dbus_assert (connection->refcount.value > 0);
02052 
02053   if (connection->refcount.value == 1)
02054     _dbus_connection_close_possibly_shared_and_unlock (connection);
02055   else
02056     CONNECTION_UNLOCK (connection);
02057 }
02058 
02059 
02069 static void
02070 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02071 {
02072   if (timeout_milliseconds == -1)
02073     _dbus_sleep_milliseconds (1000);
02074   else if (timeout_milliseconds < 100)
02075     ; /* just busy loop */
02076   else if (timeout_milliseconds <= 1000)
02077     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02078   else
02079     _dbus_sleep_milliseconds (1000);
02080 }
02081 
02082 static DBusMessage *
02083 generate_local_error_message (dbus_uint32_t serial, 
02084                               char *error_name, 
02085                               char *error_msg)
02086 {
02087   DBusMessage *message;
02088   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02089   if (!message)
02090     goto out;
02091 
02092   if (!dbus_message_set_error_name (message, error_name))
02093     {
02094       dbus_message_unref (message);
02095       message = NULL;
02096       goto out; 
02097     }
02098 
02099   dbus_message_set_no_reply (message, TRUE); 
02100 
02101   if (!dbus_message_set_reply_serial (message,
02102                                       serial))
02103     {
02104       dbus_message_unref (message);
02105       message = NULL;
02106       goto out;
02107     }
02108 
02109   if (error_msg != NULL)
02110     {
02111       DBusMessageIter iter;
02112 
02113       dbus_message_iter_init_append (message, &iter);
02114       if (!dbus_message_iter_append_basic (&iter,
02115                                            DBUS_TYPE_STRING,
02116                                            &error_msg))
02117         {
02118           dbus_message_unref (message);
02119           message = NULL;
02120           goto out;
02121         }
02122     }
02123 
02124  out:
02125   return message;
02126 }
02127 
02128 
02129 /* This is slightly strange since we can pop a message here without
02130  * the dispatch lock.
02131  */
02132 static DBusMessage*
02133 check_for_reply_unlocked (DBusConnection *connection,
02134                           dbus_uint32_t   client_serial)
02135 {
02136   DBusList *link;
02137 
02138   HAVE_LOCK_CHECK (connection);
02139   
02140   link = _dbus_list_get_first_link (&connection->incoming_messages);
02141 
02142   while (link != NULL)
02143     {
02144       DBusMessage *reply = link->data;
02145 
02146       if (dbus_message_get_reply_serial (reply) == client_serial)
02147         {
02148           _dbus_list_remove_link (&connection->incoming_messages, link);
02149           connection->n_incoming  -= 1;
02150           return reply;
02151         }
02152       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02153     }
02154 
02155   return NULL;
02156 }
02157 
02158 static void
02159 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02160 {
02161    /* We can't iterate over the hash in the normal way since we'll be
02162     * dropping the lock for each item. So we restart the
02163     * iter each time as we drain the hash table.
02164     */
02165    
02166    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02167     {
02168       DBusPendingCall *pending;
02169       DBusHashIter iter;
02170       
02171       _dbus_hash_iter_init (connection->pending_replies, &iter);
02172       _dbus_hash_iter_next (&iter);
02173        
02174       pending = _dbus_hash_iter_get_value (&iter);
02175       _dbus_pending_call_ref_unlocked (pending);
02176        
02177       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02178                                                        connection);
02179       _dbus_connection_remove_timeout_unlocked (connection,
02180                                                 _dbus_pending_call_get_timeout_unlocked (pending));
02181       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02182       _dbus_hash_iter_remove_entry (&iter);
02183 
02184       _dbus_pending_call_unref_and_unlock (pending);
02185       CONNECTION_LOCK (connection);
02186     }
02187   HAVE_LOCK_CHECK (connection);
02188 }
02189 
02190 static void
02191 complete_pending_call_and_unlock (DBusConnection  *connection,
02192                                   DBusPendingCall *pending,
02193                                   DBusMessage     *message)
02194 {
02195   _dbus_pending_call_set_reply_unlocked (pending, message);
02196   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02197   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02198  
02199   /* Must be called unlocked since it invokes app callback */
02200   _dbus_pending_call_complete (pending);
02201   dbus_pending_call_unref (pending);
02202 }
02203 
02204 static dbus_bool_t
02205 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02206                                               DBusPendingCall *pending)
02207 {
02208   DBusMessage *reply;
02209   DBusDispatchStatus status;
02210 
02211   reply = check_for_reply_unlocked (connection, 
02212                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02213   if (reply != NULL)
02214     {
02215       _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02216 
02217       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02218 
02219       complete_pending_call_and_unlock (connection, pending, reply);
02220       dbus_message_unref (reply);
02221 
02222       CONNECTION_LOCK (connection);
02223       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02224       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02225       dbus_pending_call_unref (pending);
02226 
02227       return TRUE;
02228     }
02229 
02230   return FALSE;
02231 }
02232 
02247 void
02248 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02249 {
02250   long start_tv_sec, start_tv_usec;
02251   long end_tv_sec, end_tv_usec;
02252   long tv_sec, tv_usec;
02253   DBusDispatchStatus status;
02254   DBusConnection *connection;
02255   dbus_uint32_t client_serial;
02256   int timeout_milliseconds;
02257 
02258   _dbus_assert (pending != NULL);
02259 
02260   if (dbus_pending_call_get_completed (pending))
02261     return;
02262 
02263   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02264 
02265   connection = _dbus_pending_call_get_connection_and_lock (pending);
02266   
02267   /* Flush message queue - note, can affect dispatch status */
02268   _dbus_connection_flush_unlocked (connection);
02269 
02270   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02271 
02272   /* note that timeout_milliseconds is limited to a smallish value
02273    * in _dbus_pending_call_new() so overflows aren't possible
02274    * below
02275    */
02276   timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02277   
02278   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02279   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02280   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02281   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02282   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02283 
02284   _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",
02285                  timeout_milliseconds,
02286                  client_serial,
02287                  start_tv_sec, start_tv_usec,
02288                  end_tv_sec, end_tv_usec);
02289 
02290   /* check to see if we already got the data off the socket */
02291   /* from another blocked pending call */
02292   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02293     return;
02294 
02295   /* Now we wait... */
02296   /* always block at least once as we know we don't have the reply yet */
02297   _dbus_connection_do_iteration_unlocked (connection,
02298                                           DBUS_ITERATION_DO_READING |
02299                                           DBUS_ITERATION_BLOCK,
02300                                           timeout_milliseconds);
02301 
02302  recheck_status:
02303 
02304   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02305   
02306   HAVE_LOCK_CHECK (connection);
02307   
02308   /* queue messages and get status */
02309 
02310   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02311 
02312   /* the get_completed() is in case a dispatch() while we were blocking
02313    * got the reply instead of us.
02314    */
02315   if (_dbus_pending_call_get_completed_unlocked (pending))
02316     {
02317       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02318       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02319       dbus_pending_call_unref (pending);
02320       return;
02321     }
02322   
02323   if (status == DBUS_DISPATCH_DATA_REMAINS)
02324     {
02325       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02326         return;
02327     }
02328   
02329   _dbus_get_current_time (&tv_sec, &tv_usec);
02330   
02331   if (!_dbus_connection_get_is_connected_unlocked (connection))
02332     {
02333       DBusMessage *error_msg;
02334 
02335       error_msg = generate_local_error_message (client_serial,
02336                                                 DBUS_ERROR_DISCONNECTED, 
02337                                                 "Connection was disconnected before a reply was received"); 
02338 
02339       /* on OOM error_msg is set to NULL */
02340       complete_pending_call_and_unlock (connection, pending, error_msg);
02341       dbus_pending_call_unref (pending);
02342       return;
02343     }
02344   else if (tv_sec < start_tv_sec)
02345     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02346   else if (connection->disconnect_message_link == NULL)
02347     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02348   else if (tv_sec < end_tv_sec ||
02349            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02350     {
02351       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02352         (end_tv_usec - tv_usec) / 1000;
02353       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02354       _dbus_assert (timeout_milliseconds >= 0);
02355       
02356       if (status == DBUS_DISPATCH_NEED_MEMORY)
02357         {
02358           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02359            * we may already have a reply in the buffer and just can't process
02360            * it.
02361            */
02362           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02363 
02364           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02365         }
02366       else
02367         {          
02368           /* block again, we don't have the reply buffered yet. */
02369           _dbus_connection_do_iteration_unlocked (connection,
02370                                                   DBUS_ITERATION_DO_READING |
02371                                                   DBUS_ITERATION_BLOCK,
02372                                                   timeout_milliseconds);
02373         }
02374 
02375       goto recheck_status;
02376     }
02377 
02378   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02379                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02380 
02381   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02382   
02383   /* unlock and call user code */
02384   complete_pending_call_and_unlock (connection, pending, NULL);
02385 
02386   /* update user code on dispatch status */
02387   CONNECTION_LOCK (connection);
02388   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02389   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02390   dbus_pending_call_unref (pending);
02391 }
02392 
02429 DBusConnection*
02430 dbus_connection_open (const char     *address,
02431                       DBusError      *error)
02432 {
02433   DBusConnection *connection;
02434 
02435   _dbus_return_val_if_fail (address != NULL, NULL);
02436   _dbus_return_val_if_error_is_set (error, NULL);
02437 
02438   connection = _dbus_connection_open_internal (address,
02439                                                TRUE,
02440                                                error);
02441 
02442   return connection;
02443 }
02444 
02472 DBusConnection*
02473 dbus_connection_open_private (const char     *address,
02474                               DBusError      *error)
02475 {
02476   DBusConnection *connection;
02477 
02478   _dbus_return_val_if_fail (address != NULL, NULL);
02479   _dbus_return_val_if_error_is_set (error, NULL);
02480 
02481   connection = _dbus_connection_open_internal (address,
02482                                                FALSE,
02483                                                error);
02484 
02485   return connection;
02486 }
02487 
02494 DBusConnection *
02495 dbus_connection_ref (DBusConnection *connection)
02496 {
02497   _dbus_return_val_if_fail (connection != NULL, NULL);
02498   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02499   
02500   /* The connection lock is better than the global
02501    * lock in the atomic increment fallback
02502    */
02503   
02504 #ifdef DBUS_HAVE_ATOMIC_INT
02505   _dbus_atomic_inc (&connection->refcount);
02506 #else
02507   CONNECTION_LOCK (connection);
02508   _dbus_assert (connection->refcount.value > 0);
02509 
02510   connection->refcount.value += 1;
02511   CONNECTION_UNLOCK (connection);
02512 #endif
02513 
02514   return connection;
02515 }
02516 
02517 static void
02518 free_outgoing_message (void *element,
02519                        void *data)
02520 {
02521   DBusMessage *message = element;
02522   DBusConnection *connection = data;
02523 
02524   _dbus_message_remove_size_counter (message,
02525                                      connection->outgoing_counter,
02526                                      NULL);
02527   dbus_message_unref (message);
02528 }
02529 
02530 /* This is run without the mutex held, but after the last reference
02531  * to the connection has been dropped we should have no thread-related
02532  * problems
02533  */
02534 static void
02535 _dbus_connection_last_unref (DBusConnection *connection)
02536 {
02537   DBusList *link;
02538 
02539   _dbus_verbose ("Finalizing connection %p\n", connection);
02540   
02541   _dbus_assert (connection->refcount.value == 0);
02542   
02543   /* You have to disconnect the connection before unref:ing it. Otherwise
02544    * you won't get the disconnected message.
02545    */
02546   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02547   _dbus_assert (connection->server_guid == NULL);
02548   
02549   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02550   _dbus_object_tree_free_all_unlocked (connection->objects);
02551   
02552   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02553   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02554   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02555   
02556   _dbus_watch_list_free (connection->watches);
02557   connection->watches = NULL;
02558   
02559   _dbus_timeout_list_free (connection->timeouts);
02560   connection->timeouts = NULL;
02561 
02562   _dbus_data_slot_list_free (&connection->slot_list);
02563   
02564   link = _dbus_list_get_first_link (&connection->filter_list);
02565   while (link != NULL)
02566     {
02567       DBusMessageFilter *filter = link->data;
02568       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02569 
02570       filter->function = NULL;
02571       _dbus_message_filter_unref (filter); /* calls app callback */
02572       link->data = NULL;
02573       
02574       link = next;
02575     }
02576   _dbus_list_clear (&connection->filter_list);
02577   
02578   /* ---- Done with stuff that invokes application callbacks */
02579 
02580   _dbus_object_tree_unref (connection->objects);  
02581 
02582   _dbus_hash_table_unref (connection->pending_replies);
02583   connection->pending_replies = NULL;
02584   
02585   _dbus_list_clear (&connection->filter_list);
02586   
02587   _dbus_list_foreach (&connection->outgoing_messages,
02588                       free_outgoing_message,
02589                       connection);
02590   _dbus_list_clear (&connection->outgoing_messages);
02591   
02592   _dbus_list_foreach (&connection->incoming_messages,
02593                       (DBusForeachFunction) dbus_message_unref,
02594                       NULL);
02595   _dbus_list_clear (&connection->incoming_messages);
02596 
02597   _dbus_counter_unref (connection->outgoing_counter);
02598 
02599   _dbus_transport_unref (connection->transport);
02600 
02601   if (connection->disconnect_message_link)
02602     {
02603       DBusMessage *message = connection->disconnect_message_link->data;
02604       dbus_message_unref (message);
02605       _dbus_list_free_link (connection->disconnect_message_link);
02606     }
02607 
02608   _dbus_list_clear (&connection->link_cache);
02609   
02610   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02611   _dbus_condvar_free_at_location (&connection->io_path_cond);
02612 
02613   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02614   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02615 
02616   _dbus_mutex_free_at_location (&connection->mutex);
02617   
02618   dbus_free (connection);
02619 }
02620 
02640 void
02641 dbus_connection_unref (DBusConnection *connection)
02642 {
02643   dbus_bool_t last_unref;
02644 
02645   _dbus_return_if_fail (connection != NULL);
02646   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02647   
02648   /* The connection lock is better than the global
02649    * lock in the atomic increment fallback
02650    */
02651   
02652 #ifdef DBUS_HAVE_ATOMIC_INT
02653   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02654 #else
02655   CONNECTION_LOCK (connection);
02656   
02657   _dbus_assert (connection->refcount.value > 0);
02658 
02659   connection->refcount.value -= 1;
02660   last_unref = (connection->refcount.value == 0);
02661 
02662 #if 0
02663   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02664 #endif
02665   
02666   CONNECTION_UNLOCK (connection);
02667 #endif
02668   
02669   if (last_unref)
02670     {
02671 #ifndef DBUS_DISABLE_CHECKS
02672       if (_dbus_transport_get_is_connected (connection->transport))
02673         {
02674           _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",
02675                                    connection->shareable ?
02676                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02677                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02678           return;
02679         }
02680 #endif
02681       _dbus_connection_last_unref (connection);
02682     }
02683 }
02684 
02685 /*
02686  * Note that the transport can disconnect itself (other end drops us)
02687  * and in that case this function never runs. So this function must
02688  * not do anything more than disconnect the transport and update the
02689  * dispatch status.
02690  * 
02691  * If the transport self-disconnects, then we assume someone will
02692  * dispatch the connection to cause the dispatch status update.
02693  */
02694 static void
02695 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02696 {
02697   DBusDispatchStatus status;
02698 
02699   HAVE_LOCK_CHECK (connection);
02700   
02701   _dbus_verbose ("Disconnecting %p\n", connection);
02702 
02703   /* We need to ref because update_dispatch_status_and_unlock will unref
02704    * the connection if it was shared and libdbus was the only remaining
02705    * refcount holder.
02706    */
02707   _dbus_connection_ref_unlocked (connection);
02708   
02709   _dbus_transport_disconnect (connection->transport);
02710 
02711   /* This has the side effect of queuing the disconnect message link
02712    * (unless we don't have enough memory, possibly, so don't assert it).
02713    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02714    * should never again return the newly-disconnected connection.
02715    *
02716    * However, we only unref the shared connection and exit_on_disconnect when
02717    * the disconnect message reaches the head of the message queue,
02718    * NOT when it's first queued.
02719    */
02720   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02721 
02722   /* This calls out to user code */
02723   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02724 
02725   /* Could also call out to user code */
02726   dbus_connection_unref (connection);
02727 }
02728 
02771 void
02772 dbus_connection_close (DBusConnection *connection)
02773 {
02774   _dbus_return_if_fail (connection != NULL);
02775   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02776 
02777   CONNECTION_LOCK (connection);
02778 
02779 #ifndef DBUS_DISABLE_CHECKS
02780   if (connection->shareable)
02781     {
02782       CONNECTION_UNLOCK (connection);
02783 
02784       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02785       return;
02786     }
02787 #endif
02788   
02789   _dbus_connection_close_possibly_shared_and_unlock (connection);
02790 }
02791 
02792 static dbus_bool_t
02793 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02794 {
02795   HAVE_LOCK_CHECK (connection);
02796   return _dbus_transport_get_is_connected (connection->transport);
02797 }
02798 
02812 dbus_bool_t
02813 dbus_connection_get_is_connected (DBusConnection *connection)
02814 {
02815   dbus_bool_t res;
02816 
02817   _dbus_return_val_if_fail (connection != NULL, FALSE);
02818   
02819   CONNECTION_LOCK (connection);
02820   res = _dbus_connection_get_is_connected_unlocked (connection);
02821   CONNECTION_UNLOCK (connection);
02822   
02823   return res;
02824 }
02825 
02834 dbus_bool_t
02835 dbus_connection_get_is_authenticated (DBusConnection *connection)
02836 {
02837   dbus_bool_t res;
02838 
02839   _dbus_return_val_if_fail (connection != NULL, FALSE);
02840   
02841   CONNECTION_LOCK (connection);
02842   res = _dbus_transport_get_is_authenticated (connection->transport);
02843   CONNECTION_UNLOCK (connection);
02844   
02845   return res;
02846 }
02847 
02868 dbus_bool_t
02869 dbus_connection_get_is_anonymous (DBusConnection *connection)
02870 {
02871   dbus_bool_t res;
02872 
02873   _dbus_return_val_if_fail (connection != NULL, FALSE);
02874   
02875   CONNECTION_LOCK (connection);
02876   res = _dbus_transport_get_is_anonymous (connection->transport);
02877   CONNECTION_UNLOCK (connection);
02878   
02879   return res;
02880 }
02881 
02913 char*
02914 dbus_connection_get_server_id (DBusConnection *connection)
02915 {
02916   char *id;
02917 
02918   _dbus_return_val_if_fail (connection != NULL, FALSE);
02919   
02920   CONNECTION_LOCK (connection);
02921   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02922   CONNECTION_UNLOCK (connection);
02923   
02924   return id;
02925 }
02926 
02940 void
02941 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02942                                         dbus_bool_t     exit_on_disconnect)
02943 {
02944   _dbus_return_if_fail (connection != NULL);
02945 
02946   CONNECTION_LOCK (connection);
02947   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02948   CONNECTION_UNLOCK (connection);
02949 }
02950 
02960 DBusPreallocatedSend*
02961 dbus_connection_preallocate_send (DBusConnection *connection)
02962 {
02963   DBusPreallocatedSend *preallocated;
02964 
02965   _dbus_return_val_if_fail (connection != NULL, NULL);
02966 
02967   CONNECTION_LOCK (connection);
02968   
02969   preallocated =
02970     _dbus_connection_preallocate_send_unlocked (connection);
02971 
02972   CONNECTION_UNLOCK (connection);
02973 
02974   return preallocated;
02975 }
02976 
02986 void
02987 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02988                                         DBusPreallocatedSend *preallocated)
02989 {
02990   _dbus_return_if_fail (connection != NULL);
02991   _dbus_return_if_fail (preallocated != NULL);  
02992   _dbus_return_if_fail (connection == preallocated->connection);
02993 
02994   _dbus_list_free_link (preallocated->queue_link);
02995   _dbus_counter_unref (preallocated->counter_link->data);
02996   _dbus_list_free_link (preallocated->counter_link);
02997   dbus_free (preallocated);
02998 }
02999 
03012 void
03013 dbus_connection_send_preallocated (DBusConnection       *connection,
03014                                    DBusPreallocatedSend *preallocated,
03015                                    DBusMessage          *message,
03016                                    dbus_uint32_t        *client_serial)
03017 {
03018   _dbus_return_if_fail (connection != NULL);
03019   _dbus_return_if_fail (preallocated != NULL);
03020   _dbus_return_if_fail (message != NULL);
03021   _dbus_return_if_fail (preallocated->connection == connection);
03022   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03023                         dbus_message_get_member (message) != NULL);
03024   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03025                         (dbus_message_get_interface (message) != NULL &&
03026                          dbus_message_get_member (message) != NULL));
03027   
03028   CONNECTION_LOCK (connection);
03029   _dbus_connection_send_preallocated_and_unlock (connection,
03030                                                  preallocated,
03031                                                  message, client_serial);
03032 }
03033 
03034 static dbus_bool_t
03035 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03036                                           DBusMessage    *message,
03037                                           dbus_uint32_t  *client_serial)
03038 {
03039   DBusPreallocatedSend *preallocated;
03040 
03041   _dbus_assert (connection != NULL);
03042   _dbus_assert (message != NULL);
03043   
03044   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03045   if (preallocated == NULL)
03046     return FALSE;
03047 
03048   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03049                                                          preallocated,
03050                                                          message,
03051                                                          client_serial);
03052   return TRUE;
03053 }
03054 
03076 dbus_bool_t
03077 dbus_connection_send (DBusConnection *connection,
03078                       DBusMessage    *message,
03079                       dbus_uint32_t  *serial)
03080 {
03081   _dbus_return_val_if_fail (connection != NULL, FALSE);
03082   _dbus_return_val_if_fail (message != NULL, FALSE);
03083 
03084   CONNECTION_LOCK (connection);
03085 
03086   return _dbus_connection_send_and_unlock (connection,
03087                                            message,
03088                                            serial);
03089 }
03090 
03091 static dbus_bool_t
03092 reply_handler_timeout (void *data)
03093 {
03094   DBusConnection *connection;
03095   DBusDispatchStatus status;
03096   DBusPendingCall *pending = data;
03097 
03098   connection = _dbus_pending_call_get_connection_and_lock (pending);
03099 
03100   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03101                                                    connection);
03102   _dbus_connection_remove_timeout_unlocked (connection,
03103                                             _dbus_pending_call_get_timeout_unlocked (pending));
03104   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03105 
03106   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03107   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03108 
03109   /* Unlocks, and calls out to user code */
03110   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03111   
03112   return TRUE;
03113 }
03114 
03152 dbus_bool_t
03153 dbus_connection_send_with_reply (DBusConnection     *connection,
03154                                  DBusMessage        *message,
03155                                  DBusPendingCall   **pending_return,
03156                                  int                 timeout_milliseconds)
03157 {
03158   DBusPendingCall *pending;
03159   dbus_int32_t serial = -1;
03160   DBusDispatchStatus status;
03161 
03162   _dbus_return_val_if_fail (connection != NULL, FALSE);
03163   _dbus_return_val_if_fail (message != NULL, FALSE);
03164   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03165 
03166   if (pending_return)
03167     *pending_return = NULL;
03168 
03169   CONNECTION_LOCK (connection);
03170 
03171    if (!_dbus_connection_get_is_connected_unlocked (connection))
03172     {
03173       CONNECTION_UNLOCK (connection);
03174 
03175       return TRUE;
03176     }
03177 
03178   pending = _dbus_pending_call_new_unlocked (connection,
03179                                              timeout_milliseconds,
03180                                              reply_handler_timeout);
03181 
03182   if (pending == NULL)
03183     {
03184       CONNECTION_UNLOCK (connection);
03185       return FALSE;
03186     }
03187 
03188   /* Assign a serial to the message */
03189   serial = dbus_message_get_serial (message);
03190   if (serial == 0)
03191     {
03192       serial = _dbus_connection_get_next_client_serial (connection);
03193       _dbus_message_set_serial (message, serial);
03194     }
03195 
03196   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03197     goto error;
03198     
03199   /* Insert the serial in the pending replies hash;
03200    * hash takes a refcount on DBusPendingCall.
03201    * Also, add the timeout.
03202    */
03203   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03204                                                       pending))
03205     goto error;
03206  
03207   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03208     {
03209       _dbus_connection_detach_pending_call_and_unlock (connection,
03210                                                        pending);
03211       goto error_unlocked;
03212     }
03213 
03214   if (pending_return)
03215     *pending_return = pending; /* hand off refcount */
03216   else
03217     {
03218       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03219       /* we still have a ref to the pending call in this case, we unref
03220        * after unlocking, below
03221        */
03222     }
03223 
03224   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03225 
03226   /* this calls out to user code */
03227   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03228 
03229   if (pending_return == NULL)
03230     dbus_pending_call_unref (pending);
03231   
03232   return TRUE;
03233 
03234  error:
03235   CONNECTION_UNLOCK (connection);
03236  error_unlocked:
03237   dbus_pending_call_unref (pending);
03238   return FALSE;
03239 }
03240 
03271 DBusMessage*
03272 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03273                                            DBusMessage        *message,
03274                                            int                 timeout_milliseconds,
03275                                            DBusError          *error)
03276 {
03277   DBusMessage *reply;
03278   DBusPendingCall *pending;
03279   
03280   _dbus_return_val_if_fail (connection != NULL, NULL);
03281   _dbus_return_val_if_fail (message != NULL, NULL);
03282   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03283   _dbus_return_val_if_error_is_set (error, NULL);
03284   
03285   if (!dbus_connection_send_with_reply (connection, message,
03286                                         &pending, timeout_milliseconds))
03287     {
03288       _DBUS_SET_OOM (error);
03289       return NULL;
03290     }
03291 
03292   if (pending == NULL)
03293     {
03294       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03295       return NULL;
03296     }
03297   
03298   dbus_pending_call_block (pending);
03299 
03300   reply = dbus_pending_call_steal_reply (pending);
03301   dbus_pending_call_unref (pending);
03302 
03303   /* call_complete_and_unlock() called from pending_call_block() should
03304    * always fill this in.
03305    */
03306   _dbus_assert (reply != NULL);
03307   
03308    if (dbus_set_error_from_message (error, reply))
03309     {
03310       dbus_message_unref (reply);
03311       return NULL;
03312     }
03313   else
03314     return reply;
03315 }
03316 
03325 DBusDispatchStatus
03326 _dbus_connection_flush_unlocked (DBusConnection *connection)
03327 {
03328   /* We have to specify DBUS_ITERATION_DO_READING here because
03329    * otherwise we could have two apps deadlock if they are both doing
03330    * a flush(), and the kernel buffers fill up. This could change the
03331    * dispatch status.
03332    */
03333   DBusDispatchStatus status;
03334 
03335   HAVE_LOCK_CHECK (connection);
03336   
03337   while (connection->n_outgoing > 0 &&
03338          _dbus_connection_get_is_connected_unlocked (connection))
03339     {
03340       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03341       HAVE_LOCK_CHECK (connection);
03342       _dbus_connection_do_iteration_unlocked (connection,
03343                                               DBUS_ITERATION_DO_READING |
03344                                               DBUS_ITERATION_DO_WRITING |
03345                                               DBUS_ITERATION_BLOCK,
03346                                               -1);
03347     }
03348 
03349   HAVE_LOCK_CHECK (connection);
03350   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03351   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03352 
03353   HAVE_LOCK_CHECK (connection);
03354   return status;
03355 }
03356 
03362 void
03363 dbus_connection_flush (DBusConnection *connection)
03364 {
03365   /* We have to specify DBUS_ITERATION_DO_READING here because
03366    * otherwise we could have two apps deadlock if they are both doing
03367    * a flush(), and the kernel buffers fill up. This could change the
03368    * dispatch status.
03369    */
03370   DBusDispatchStatus status;
03371 
03372   _dbus_return_if_fail (connection != NULL);
03373   
03374   CONNECTION_LOCK (connection);
03375 
03376   status = _dbus_connection_flush_unlocked (connection);
03377   
03378   HAVE_LOCK_CHECK (connection);
03379   /* Unlocks and calls out to user code */
03380   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03381 
03382   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03383 }
03384 
03395 static dbus_bool_t
03396 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03397                                      int             timeout_milliseconds, 
03398                                      dbus_bool_t     dispatch)
03399 {
03400   DBusDispatchStatus dstatus;
03401   dbus_bool_t no_progress_possible;
03402   
03403   dstatus = dbus_connection_get_dispatch_status (connection);
03404 
03405   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03406     {
03407       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03408       dbus_connection_dispatch (connection);
03409       CONNECTION_LOCK (connection);
03410     }
03411   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03412     {
03413       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03414       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03415       CONNECTION_LOCK (connection);
03416     }
03417   else
03418     {
03419       CONNECTION_LOCK (connection);
03420       if (_dbus_connection_get_is_connected_unlocked (connection))
03421         {
03422           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03423           _dbus_connection_do_iteration_unlocked (connection,
03424                                                   DBUS_ITERATION_DO_READING |
03425                                                   DBUS_ITERATION_DO_WRITING |
03426                                                   DBUS_ITERATION_BLOCK,
03427                                                   timeout_milliseconds);
03428         }
03429     }
03430   
03431   HAVE_LOCK_CHECK (connection);
03432   /* If we can dispatch, we can make progress until the Disconnected message
03433    * has been processed; if we can only read/write, we can make progress
03434    * as long as the transport is open.
03435    */
03436   if (dispatch)
03437     no_progress_possible = connection->n_incoming == 0 &&
03438       connection->disconnect_message_link == NULL;
03439   else
03440     no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03441   CONNECTION_UNLOCK (connection);
03442   return !no_progress_possible; /* TRUE if we can make more progress */
03443 }
03444 
03445 
03480 dbus_bool_t
03481 dbus_connection_read_write_dispatch (DBusConnection *connection,
03482                                      int             timeout_milliseconds)
03483 {
03484   _dbus_return_val_if_fail (connection != NULL, FALSE);
03485   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03486    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03487 }
03488 
03512 dbus_bool_t 
03513 dbus_connection_read_write (DBusConnection *connection, 
03514                             int             timeout_milliseconds) 
03515 { 
03516   _dbus_return_val_if_fail (connection != NULL, FALSE);
03517   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03518    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03519 }
03520 
03521 /* We need to call this anytime we pop the head of the queue, and then
03522  * update_dispatch_status_and_unlock needs to be called afterward
03523  * which will "process" the disconnected message and set
03524  * disconnected_message_processed.
03525  */
03526 static void
03527 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03528                                              DBusMessage    *head_of_queue)
03529 {
03530   HAVE_LOCK_CHECK (connection);
03531 
03532   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03533   if (connection->disconnect_message_link == NULL &&
03534       dbus_message_is_signal (head_of_queue,
03535                               DBUS_INTERFACE_LOCAL,
03536                               "Disconnected"))
03537     {
03538       connection->disconnected_message_arrived = TRUE;
03539     }
03540 }
03541 
03561 DBusMessage*
03562 dbus_connection_borrow_message (DBusConnection *connection)
03563 {
03564   DBusDispatchStatus status;
03565   DBusMessage *message;
03566 
03567   _dbus_return_val_if_fail (connection != NULL, NULL);
03568 
03569   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03570   
03571   /* this is called for the side effect that it queues
03572    * up any messages from the transport
03573    */
03574   status = dbus_connection_get_dispatch_status (connection);
03575   if (status != DBUS_DISPATCH_DATA_REMAINS)
03576     return NULL;
03577   
03578   CONNECTION_LOCK (connection);
03579 
03580   _dbus_connection_acquire_dispatch (connection);
03581 
03582   /* While a message is outstanding, the dispatch lock is held */
03583   _dbus_assert (connection->message_borrowed == NULL);
03584 
03585   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03586   
03587   message = connection->message_borrowed;
03588 
03589   check_disconnected_message_arrived_unlocked (connection, message);
03590   
03591   /* Note that we KEEP the dispatch lock until the message is returned */
03592   if (message == NULL)
03593     _dbus_connection_release_dispatch (connection);
03594 
03595   CONNECTION_UNLOCK (connection);
03596 
03597   /* We don't update dispatch status until it's returned or stolen */
03598   
03599   return message;
03600 }
03601 
03610 void
03611 dbus_connection_return_message (DBusConnection *connection,
03612                                 DBusMessage    *message)
03613 {
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   connection->message_borrowed = NULL;
03626 
03627   _dbus_connection_release_dispatch (connection); 
03628 
03629   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03630   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03631 }
03632 
03642 void
03643 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03644                                         DBusMessage    *message)
03645 {
03646   DBusMessage *pop_message;
03647   DBusDispatchStatus status;
03648 
03649   _dbus_return_if_fail (connection != NULL);
03650   _dbus_return_if_fail (message != NULL);
03651   _dbus_return_if_fail (message == connection->message_borrowed);
03652   _dbus_return_if_fail (connection->dispatch_acquired);
03653   
03654   CONNECTION_LOCK (connection);
03655  
03656   _dbus_assert (message == connection->message_borrowed);
03657 
03658   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03659   _dbus_assert (message == pop_message);
03660   
03661   connection->n_incoming -= 1;
03662  
03663   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03664                  message, connection->n_incoming);
03665  
03666   connection->message_borrowed = NULL;
03667 
03668   _dbus_connection_release_dispatch (connection);
03669 
03670   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03671   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03672 }
03673 
03674 /* See dbus_connection_pop_message, but requires the caller to own
03675  * the lock before calling. May drop the lock while running.
03676  */
03677 static DBusList*
03678 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03679 {
03680   HAVE_LOCK_CHECK (connection);
03681   
03682   _dbus_assert (connection->message_borrowed == NULL);
03683   
03684   if (connection->n_incoming > 0)
03685     {
03686       DBusList *link;
03687 
03688       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03689       connection->n_incoming -= 1;
03690 
03691       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03692                      link->data,
03693                      dbus_message_get_type (link->data),
03694                      dbus_message_get_path (link->data) ?
03695                      dbus_message_get_path (link->data) :
03696                      "no path",
03697                      dbus_message_get_interface (link->data) ?
03698                      dbus_message_get_interface (link->data) :
03699                      "no interface",
03700                      dbus_message_get_member (link->data) ?
03701                      dbus_message_get_member (link->data) :
03702                      "no member",
03703                      dbus_message_get_signature (link->data),
03704                      connection, connection->n_incoming);
03705 
03706       check_disconnected_message_arrived_unlocked (connection, link->data);
03707       
03708       return link;
03709     }
03710   else
03711     return NULL;
03712 }
03713 
03714 /* See dbus_connection_pop_message, but requires the caller to own
03715  * the lock before calling. May drop the lock while running.
03716  */
03717 static DBusMessage*
03718 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03719 {
03720   DBusList *link;
03721 
03722   HAVE_LOCK_CHECK (connection);
03723   
03724   link = _dbus_connection_pop_message_link_unlocked (connection);
03725 
03726   if (link != NULL)
03727     {
03728       DBusMessage *message;
03729       
03730       message = link->data;
03731       
03732       _dbus_list_free_link (link);
03733       
03734       return message;
03735     }
03736   else
03737     return NULL;
03738 }
03739 
03740 static void
03741 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03742                                                 DBusList       *message_link)
03743 {
03744   HAVE_LOCK_CHECK (connection);
03745   
03746   _dbus_assert (message_link != NULL);
03747   /* You can't borrow a message while a link is outstanding */
03748   _dbus_assert (connection->message_borrowed == NULL);
03749   /* We had to have the dispatch lock across the pop/putback */
03750   _dbus_assert (connection->dispatch_acquired);
03751 
03752   _dbus_list_prepend_link (&connection->incoming_messages,
03753                            message_link);
03754   connection->n_incoming += 1;
03755 
03756   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03757                  message_link->data,
03758                  dbus_message_get_type (message_link->data),
03759                  dbus_message_get_interface (message_link->data) ?
03760                  dbus_message_get_interface (message_link->data) :
03761                  "no interface",
03762                  dbus_message_get_member (message_link->data) ?
03763                  dbus_message_get_member (message_link->data) :
03764                  "no member",
03765                  dbus_message_get_signature (message_link->data),
03766                  connection, connection->n_incoming);
03767 }
03768 
03788 DBusMessage*
03789 dbus_connection_pop_message (DBusConnection *connection)
03790 {
03791   DBusMessage *message;
03792   DBusDispatchStatus status;
03793 
03794   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03795   
03796   /* this is called for the side effect that it queues
03797    * up any messages from the transport
03798    */
03799   status = dbus_connection_get_dispatch_status (connection);
03800   if (status != DBUS_DISPATCH_DATA_REMAINS)
03801     return NULL;
03802   
03803   CONNECTION_LOCK (connection);
03804   _dbus_connection_acquire_dispatch (connection);
03805   HAVE_LOCK_CHECK (connection);
03806   
03807   message = _dbus_connection_pop_message_unlocked (connection);
03808 
03809   _dbus_verbose ("Returning popped message %p\n", message);    
03810 
03811   _dbus_connection_release_dispatch (connection);
03812 
03813   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03814   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03815   
03816   return message;
03817 }
03818 
03826 static void
03827 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03828 {
03829   HAVE_LOCK_CHECK (connection);
03830 
03831   _dbus_connection_ref_unlocked (connection);
03832   CONNECTION_UNLOCK (connection);
03833   
03834   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03835   _dbus_mutex_lock (connection->dispatch_mutex);
03836 
03837   while (connection->dispatch_acquired)
03838     {
03839       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03840       _dbus_condvar_wait (connection->dispatch_cond, 
03841                           connection->dispatch_mutex);
03842     }
03843   
03844   _dbus_assert (!connection->dispatch_acquired);
03845 
03846   connection->dispatch_acquired = TRUE;
03847 
03848   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03849   _dbus_mutex_unlock (connection->dispatch_mutex);
03850   
03851   CONNECTION_LOCK (connection);
03852   _dbus_connection_unref_unlocked (connection);
03853 }
03854 
03862 static void
03863 _dbus_connection_release_dispatch (DBusConnection *connection)
03864 {
03865   HAVE_LOCK_CHECK (connection);
03866   
03867   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03868   _dbus_mutex_lock (connection->dispatch_mutex);
03869   
03870   _dbus_assert (connection->dispatch_acquired);
03871 
03872   connection->dispatch_acquired = FALSE;
03873   _dbus_condvar_wake_one (connection->dispatch_cond);
03874 
03875   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03876   _dbus_mutex_unlock (connection->dispatch_mutex);
03877 }
03878 
03879 static void
03880 _dbus_connection_failed_pop (DBusConnection *connection,
03881                              DBusList       *message_link)
03882 {
03883   _dbus_list_prepend_link (&connection->incoming_messages,
03884                            message_link);
03885   connection->n_incoming += 1;
03886 }
03887 
03888 /* Note this may be called multiple times since we don't track whether we already did it */
03889 static void
03890 notify_disconnected_unlocked (DBusConnection *connection)
03891 {
03892   HAVE_LOCK_CHECK (connection);
03893 
03894   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
03895    * connection from dbus_bus_get(). We make the same guarantee for
03896    * dbus_connection_open() but in a different way since we don't want to
03897    * unref right here; we instead check for connectedness before returning
03898    * the connection from the hash.
03899    */
03900   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03901 
03902   /* Dump the outgoing queue, we aren't going to be able to
03903    * send it now, and we'd like accessors like
03904    * dbus_connection_get_outgoing_size() to be accurate.
03905    */
03906   if (connection->n_outgoing > 0)
03907     {
03908       DBusList *link;
03909       
03910       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03911                      connection->n_outgoing);
03912       
03913       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03914         {
03915           _dbus_connection_message_sent (connection, link->data);
03916         }
03917     } 
03918 }
03919 
03920 /* Note this may be called multiple times since we don't track whether we already did it */
03921 static DBusDispatchStatus
03922 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03923 {
03924   HAVE_LOCK_CHECK (connection);
03925   
03926   if (connection->disconnect_message_link != NULL)
03927     {
03928       _dbus_verbose ("Sending disconnect message from %s\n",
03929                      _DBUS_FUNCTION_NAME);
03930       
03931       /* If we have pending calls, queue their timeouts - we want the Disconnected
03932        * to be the last message, after these timeouts.
03933        */
03934       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03935       
03936       /* We haven't sent the disconnect message already,
03937        * and all real messages have been queued up.
03938        */
03939       _dbus_connection_queue_synthesized_message_link (connection,
03940                                                        connection->disconnect_message_link);
03941       connection->disconnect_message_link = NULL;
03942 
03943       return DBUS_DISPATCH_DATA_REMAINS;
03944     }
03945 
03946   return DBUS_DISPATCH_COMPLETE;
03947 }
03948 
03949 static DBusDispatchStatus
03950 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03951 {
03952   HAVE_LOCK_CHECK (connection);
03953   
03954   if (connection->n_incoming > 0)
03955     return DBUS_DISPATCH_DATA_REMAINS;
03956   else if (!_dbus_transport_queue_messages (connection->transport))
03957     return DBUS_DISPATCH_NEED_MEMORY;
03958   else
03959     {
03960       DBusDispatchStatus status;
03961       dbus_bool_t is_connected;
03962       
03963       status = _dbus_transport_get_dispatch_status (connection->transport);
03964       is_connected = _dbus_transport_get_is_connected (connection->transport);
03965 
03966       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03967                      DISPATCH_STATUS_NAME (status), is_connected);
03968       
03969       if (!is_connected)
03970         {
03971           /* It's possible this would be better done by having an explicit
03972            * notification from _dbus_transport_disconnect() that would
03973            * synchronously do this, instead of waiting for the next dispatch
03974            * status check. However, probably not good to change until it causes
03975            * a problem.
03976            */
03977           notify_disconnected_unlocked (connection);
03978 
03979           /* I'm not sure this is needed; the idea is that we want to
03980            * queue the Disconnected only after we've read all the
03981            * messages, but if we're disconnected maybe we are guaranteed
03982            * to have read them all ?
03983            */
03984           if (status == DBUS_DISPATCH_COMPLETE)
03985             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03986         }
03987       
03988       if (status != DBUS_DISPATCH_COMPLETE)
03989         return status;
03990       else if (connection->n_incoming > 0)
03991         return DBUS_DISPATCH_DATA_REMAINS;
03992       else
03993         return DBUS_DISPATCH_COMPLETE;
03994     }
03995 }
03996 
03997 static void
03998 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03999                                                     DBusDispatchStatus new_status)
04000 {
04001   dbus_bool_t changed;
04002   DBusDispatchStatusFunction function;
04003   void *data;
04004 
04005   HAVE_LOCK_CHECK (connection);
04006 
04007   _dbus_connection_ref_unlocked (connection);
04008 
04009   changed = new_status != connection->last_dispatch_status;
04010 
04011   connection->last_dispatch_status = new_status;
04012 
04013   function = connection->dispatch_status_function;
04014   data = connection->dispatch_status_data;
04015 
04016   if (connection->disconnected_message_arrived &&
04017       !connection->disconnected_message_processed)
04018     {
04019       connection->disconnected_message_processed = TRUE;
04020       
04021       /* this does an unref, but we have a ref
04022        * so we should not run the finalizer here
04023        * inside the lock.
04024        */
04025       connection_forget_shared_unlocked (connection);
04026 
04027       if (connection->exit_on_disconnect)
04028         {
04029           CONNECTION_UNLOCK (connection);            
04030           
04031           _dbus_verbose ("Exiting on Disconnected signal\n");
04032           _dbus_exit (1);
04033           _dbus_assert_not_reached ("Call to exit() returned");
04034         }
04035     }
04036   
04037   /* We drop the lock */
04038   CONNECTION_UNLOCK (connection);
04039   
04040   if (changed && function)
04041     {
04042       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04043                      connection, new_status,
04044                      DISPATCH_STATUS_NAME (new_status));
04045       (* function) (connection, new_status, data);      
04046     }
04047   
04048   dbus_connection_unref (connection);
04049 }
04050 
04076 DBusDispatchStatus
04077 dbus_connection_get_dispatch_status (DBusConnection *connection)
04078 {
04079   DBusDispatchStatus status;
04080 
04081   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04082 
04083   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04084   
04085   CONNECTION_LOCK (connection);
04086 
04087   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04088   
04089   CONNECTION_UNLOCK (connection);
04090 
04091   return status;
04092 }
04093 
04097 static DBusHandlerResult
04098 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04099                                                  DBusMessage    *message)
04100 {
04101   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04102     {
04103       /* This means we're letting the bus route this message */
04104       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04105     }
04106   else if (dbus_message_is_method_call (message,
04107                                         DBUS_INTERFACE_PEER,
04108                                         "Ping"))
04109     {
04110       DBusMessage *ret;
04111       dbus_bool_t sent;
04112       
04113       ret = dbus_message_new_method_return (message);
04114       if (ret == NULL)
04115         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04116      
04117       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
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_is_method_call (message,
04127                                         DBUS_INTERFACE_PEER,
04128                                         "GetMachineId"))
04129     {
04130       DBusMessage *ret;
04131       dbus_bool_t sent;
04132       DBusString uuid;
04133       
04134       ret = dbus_message_new_method_return (message);
04135       if (ret == NULL)
04136         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04137 
04138       sent = FALSE;
04139       _dbus_string_init (&uuid);
04140       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04141         {
04142           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04143           if (dbus_message_append_args (ret,
04144                                         DBUS_TYPE_STRING, &v_STRING,
04145                                         DBUS_TYPE_INVALID))
04146             {
04147               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04148             }
04149         }
04150       _dbus_string_free (&uuid);
04151       
04152       dbus_message_unref (ret);
04153 
04154       if (!sent)
04155         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04156       
04157       return DBUS_HANDLER_RESULT_HANDLED;
04158     }
04159   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04160     {
04161       /* We need to bounce anything else with this interface, otherwise apps
04162        * could start extending the interface and when we added extensions
04163        * here to DBusConnection we'd break those apps.
04164        */
04165       
04166       DBusMessage *ret;
04167       dbus_bool_t sent;
04168       
04169       ret = dbus_message_new_error (message,
04170                                     DBUS_ERROR_UNKNOWN_METHOD,
04171                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04172       if (ret == NULL)
04173         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04174       
04175       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04176       
04177       dbus_message_unref (ret);
04178       
04179       if (!sent)
04180         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04181       
04182       return DBUS_HANDLER_RESULT_HANDLED;
04183     }
04184   else
04185     {
04186       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04187     }
04188 }
04189 
04196 static DBusHandlerResult
04197 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04198                                                            DBusMessage    *message)
04199 {
04200   /* We just run one filter for now but have the option to run more
04201      if the spec calls for it in the future */
04202 
04203   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04204 }
04205 
04248 DBusDispatchStatus
04249 dbus_connection_dispatch (DBusConnection *connection)
04250 {
04251   DBusMessage *message;
04252   DBusList *link, *filter_list_copy, *message_link;
04253   DBusHandlerResult result;
04254   DBusPendingCall *pending;
04255   dbus_int32_t reply_serial;
04256   DBusDispatchStatus status;
04257 
04258   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04259 
04260   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04261   
04262   CONNECTION_LOCK (connection);
04263   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04264   if (status != DBUS_DISPATCH_DATA_REMAINS)
04265     {
04266       /* unlocks and calls out to user code */
04267       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04268       return status;
04269     }
04270   
04271   /* We need to ref the connection since the callback could potentially
04272    * drop the last ref to it
04273    */
04274   _dbus_connection_ref_unlocked (connection);
04275 
04276   _dbus_connection_acquire_dispatch (connection);
04277   HAVE_LOCK_CHECK (connection);
04278 
04279   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04280   if (message_link == NULL)
04281     {
04282       /* another thread dispatched our stuff */
04283 
04284       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04285       
04286       _dbus_connection_release_dispatch (connection);
04287 
04288       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04289 
04290       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04291       
04292       dbus_connection_unref (connection);
04293       
04294       return status;
04295     }
04296 
04297   message = message_link->data;
04298 
04299   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04300                  message,
04301                  dbus_message_get_type (message),
04302                  dbus_message_get_interface (message) ?
04303                  dbus_message_get_interface (message) :
04304                  "no interface",
04305                  dbus_message_get_member (message) ?
04306                  dbus_message_get_member (message) :
04307                  "no member",
04308                  dbus_message_get_signature (message));
04309 
04310   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04311   
04312   /* Pending call handling must be first, because if you do
04313    * dbus_connection_send_with_reply_and_block() or
04314    * dbus_pending_call_block() then no handlers/filters will be run on
04315    * the reply. We want consistent semantics in the case where we
04316    * dbus_connection_dispatch() the reply.
04317    */
04318   
04319   reply_serial = dbus_message_get_reply_serial (message);
04320   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04321                                          reply_serial);
04322   if (pending)
04323     {
04324       _dbus_verbose ("Dispatching a pending reply\n");
04325       complete_pending_call_and_unlock (connection, pending, message);
04326       pending = NULL; /* it's probably unref'd */
04327       
04328       CONNECTION_LOCK (connection);
04329       _dbus_verbose ("pending call completed in dispatch\n");
04330       result = DBUS_HANDLER_RESULT_HANDLED;
04331       goto out;
04332     }
04333 
04334   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04335   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04336     goto out;
04337  
04338   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04339     {
04340       _dbus_connection_release_dispatch (connection);
04341       HAVE_LOCK_CHECK (connection);
04342       
04343       _dbus_connection_failed_pop (connection, message_link);
04344 
04345       /* unlocks and calls user code */
04346       _dbus_connection_update_dispatch_status_and_unlock (connection,
04347                                                           DBUS_DISPATCH_NEED_MEMORY);
04348 
04349       if (pending)
04350         dbus_pending_call_unref (pending);
04351       dbus_connection_unref (connection);
04352       
04353       return DBUS_DISPATCH_NEED_MEMORY;
04354     }
04355   
04356   _dbus_list_foreach (&filter_list_copy,
04357                       (DBusForeachFunction)_dbus_message_filter_ref,
04358                       NULL);
04359 
04360   /* We're still protected from dispatch() reentrancy here
04361    * since we acquired the dispatcher
04362    */
04363   CONNECTION_UNLOCK (connection);
04364   
04365   link = _dbus_list_get_first_link (&filter_list_copy);
04366   while (link != NULL)
04367     {
04368       DBusMessageFilter *filter = link->data;
04369       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04370 
04371       if (filter->function == NULL)
04372         {
04373           _dbus_verbose ("  filter was removed in a callback function\n");
04374           link = next;
04375           continue;
04376         }
04377 
04378       _dbus_verbose ("  running filter on message %p\n", message);
04379       result = (* filter->function) (connection, message, filter->user_data);
04380 
04381       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04382         break;
04383 
04384       link = next;
04385     }
04386 
04387   _dbus_list_foreach (&filter_list_copy,
04388                       (DBusForeachFunction)_dbus_message_filter_unref,
04389                       NULL);
04390   _dbus_list_clear (&filter_list_copy);
04391   
04392   CONNECTION_LOCK (connection);
04393 
04394   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04395     {
04396       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04397       goto out;
04398     }
04399   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04400     {
04401       _dbus_verbose ("filter handled message in dispatch\n");
04402       goto out;
04403     }
04404 
04405   /* We're still protected from dispatch() reentrancy here
04406    * since we acquired the dispatcher
04407    */
04408   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
04409                  message,
04410                  dbus_message_get_type (message),
04411                  dbus_message_get_interface (message) ?
04412                  dbus_message_get_interface (message) :
04413                  "no interface",
04414                  dbus_message_get_member (message) ?
04415                  dbus_message_get_member (message) :
04416                  "no member",
04417                  dbus_message_get_signature (message));
04418 
04419   HAVE_LOCK_CHECK (connection);
04420   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04421                                                   message);
04422   
04423   CONNECTION_LOCK (connection);
04424 
04425   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04426     {
04427       _dbus_verbose ("object tree handled message in dispatch\n");
04428       goto out;
04429     }
04430 
04431   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04432     {
04433       DBusMessage *reply;
04434       DBusString str;
04435       DBusPreallocatedSend *preallocated;
04436 
04437       _dbus_verbose ("  sending error %s\n",
04438                      DBUS_ERROR_UNKNOWN_METHOD);
04439       
04440       if (!_dbus_string_init (&str))
04441         {
04442           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04443           _dbus_verbose ("no memory for error string in dispatch\n");
04444           goto out;
04445         }
04446               
04447       if (!_dbus_string_append_printf (&str,
04448                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04449                                        dbus_message_get_member (message),
04450                                        dbus_message_get_signature (message),
04451                                        dbus_message_get_interface (message)))
04452         {
04453           _dbus_string_free (&str);
04454           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04455           _dbus_verbose ("no memory for error string in dispatch\n");
04456           goto out;
04457         }
04458       
04459       reply = dbus_message_new_error (message,
04460                                       DBUS_ERROR_UNKNOWN_METHOD,
04461                                       _dbus_string_get_const_data (&str));
04462       _dbus_string_free (&str);
04463 
04464       if (reply == NULL)
04465         {
04466           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04467           _dbus_verbose ("no memory for error reply in dispatch\n");
04468           goto out;
04469         }
04470       
04471       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04472 
04473       if (preallocated == NULL)
04474         {
04475           dbus_message_unref (reply);
04476           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04477           _dbus_verbose ("no memory for error send in dispatch\n");
04478           goto out;
04479         }
04480 
04481       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04482                                                              reply, NULL);
04483 
04484       dbus_message_unref (reply);
04485       
04486       result = DBUS_HANDLER_RESULT_HANDLED;
04487     }
04488   
04489   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04490                  dbus_message_get_type (message),
04491                  dbus_message_get_interface (message) ?
04492                  dbus_message_get_interface (message) :
04493                  "no interface",
04494                  dbus_message_get_member (message) ?
04495                  dbus_message_get_member (message) :
04496                  "no member",
04497                  dbus_message_get_signature (message),
04498                  connection);
04499   
04500  out:
04501   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04502     {
04503       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04504       
04505       /* Put message back, and we'll start over.
04506        * Yes this means handlers must be idempotent if they
04507        * don't return HANDLED; c'est la vie.
04508        */
04509       _dbus_connection_putback_message_link_unlocked (connection,
04510                                                       message_link);
04511     }
04512   else
04513     {
04514       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04515       
04516       _dbus_list_free_link (message_link);
04517       dbus_message_unref (message); /* don't want the message to count in max message limits
04518                                      * in computing dispatch status below
04519                                      */
04520     }
04521   
04522   _dbus_connection_release_dispatch (connection);
04523   HAVE_LOCK_CHECK (connection);
04524 
04525   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04526   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04527 
04528   /* unlocks and calls user code */
04529   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04530   
04531   dbus_connection_unref (connection);
04532   
04533   return status;
04534 }
04535 
04595 dbus_bool_t
04596 dbus_connection_set_watch_functions (DBusConnection              *connection,
04597                                      DBusAddWatchFunction         add_function,
04598                                      DBusRemoveWatchFunction      remove_function,
04599                                      DBusWatchToggledFunction     toggled_function,
04600                                      void                        *data,
04601                                      DBusFreeFunction             free_data_function)
04602 {
04603   dbus_bool_t retval;
04604   DBusWatchList *watches;
04605 
04606   _dbus_return_val_if_fail (connection != NULL, FALSE);
04607   
04608   CONNECTION_LOCK (connection);
04609 
04610 #ifndef DBUS_DISABLE_CHECKS
04611   if (connection->watches == NULL)
04612     {
04613       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04614                                _DBUS_FUNCTION_NAME);
04615       return FALSE;
04616     }
04617 #endif
04618   
04619   /* ref connection for slightly better reentrancy */
04620   _dbus_connection_ref_unlocked (connection);
04621 
04622   /* This can call back into user code, and we need to drop the
04623    * connection lock when it does. This is kind of a lame
04624    * way to do it.
04625    */
04626   watches = connection->watches;
04627   connection->watches = NULL;
04628   CONNECTION_UNLOCK (connection);
04629 
04630   retval = _dbus_watch_list_set_functions (watches,
04631                                            add_function, remove_function,
04632                                            toggled_function,
04633                                            data, free_data_function);
04634   CONNECTION_LOCK (connection);
04635   connection->watches = watches;
04636   
04637   CONNECTION_UNLOCK (connection);
04638   /* drop our paranoid refcount */
04639   dbus_connection_unref (connection);
04640   
04641   return retval;
04642 }
04643 
04677 dbus_bool_t
04678 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04679                                          DBusAddTimeoutFunction     add_function,
04680                                          DBusRemoveTimeoutFunction  remove_function,
04681                                          DBusTimeoutToggledFunction toggled_function,
04682                                          void                      *data,
04683                                          DBusFreeFunction           free_data_function)
04684 {
04685   dbus_bool_t retval;
04686   DBusTimeoutList *timeouts;
04687 
04688   _dbus_return_val_if_fail (connection != NULL, FALSE);
04689   
04690   CONNECTION_LOCK (connection);
04691 
04692 #ifndef DBUS_DISABLE_CHECKS
04693   if (connection->timeouts == NULL)
04694     {
04695       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04696                                _DBUS_FUNCTION_NAME);
04697       return FALSE;
04698     }
04699 #endif
04700   
04701   /* ref connection for slightly better reentrancy */
04702   _dbus_connection_ref_unlocked (connection);
04703 
04704   timeouts = connection->timeouts;
04705   connection->timeouts = NULL;
04706   CONNECTION_UNLOCK (connection);
04707   
04708   retval = _dbus_timeout_list_set_functions (timeouts,
04709                                              add_function, remove_function,
04710                                              toggled_function,
04711                                              data, free_data_function);
04712   CONNECTION_LOCK (connection);
04713   connection->timeouts = timeouts;
04714   
04715   CONNECTION_UNLOCK (connection);
04716   /* drop our paranoid refcount */
04717   dbus_connection_unref (connection);
04718 
04719   return retval;
04720 }
04721 
04736 void
04737 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04738                                           DBusWakeupMainFunction     wakeup_main_function,
04739                                           void                      *data,
04740                                           DBusFreeFunction           free_data_function)
04741 {
04742   void *old_data;
04743   DBusFreeFunction old_free_data;
04744 
04745   _dbus_return_if_fail (connection != NULL);
04746   
04747   CONNECTION_LOCK (connection);
04748   old_data = connection->wakeup_main_data;
04749   old_free_data = connection->free_wakeup_main_data;
04750 
04751   connection->wakeup_main_function = wakeup_main_function;
04752   connection->wakeup_main_data = data;
04753   connection->free_wakeup_main_data = free_data_function;
04754   
04755   CONNECTION_UNLOCK (connection);
04756 
04757   /* Callback outside the lock */
04758   if (old_free_data)
04759     (*old_free_data) (old_data);
04760 }
04761 
04782 void
04783 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04784                                               DBusDispatchStatusFunction  function,
04785                                               void                       *data,
04786                                               DBusFreeFunction            free_data_function)
04787 {
04788   void *old_data;
04789   DBusFreeFunction old_free_data;
04790 
04791   _dbus_return_if_fail (connection != NULL);
04792   
04793   CONNECTION_LOCK (connection);
04794   old_data = connection->dispatch_status_data;
04795   old_free_data = connection->free_dispatch_status_data;
04796 
04797   connection->dispatch_status_function = function;
04798   connection->dispatch_status_data = data;
04799   connection->free_dispatch_status_data = free_data_function;
04800   
04801   CONNECTION_UNLOCK (connection);
04802 
04803   /* Callback outside the lock */
04804   if (old_free_data)
04805     (*old_free_data) (old_data);
04806 }
04807 
04827 dbus_bool_t
04828 dbus_connection_get_unix_fd (DBusConnection *connection,
04829                              int            *fd)
04830 {
04831   _dbus_return_val_if_fail (connection != NULL, FALSE);
04832   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04833 
04834 #ifdef DBUS_WIN
04835   /* FIXME do this on a lower level */
04836   return FALSE;
04837 #endif
04838   
04839   return dbus_connection_get_socket(connection, fd);
04840 }
04841 
04857 dbus_bool_t
04858 dbus_connection_get_socket(DBusConnection              *connection,
04859                            int                         *fd)
04860 {
04861   dbus_bool_t retval;
04862 
04863   _dbus_return_val_if_fail (connection != NULL, FALSE);
04864   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04865   
04866   CONNECTION_LOCK (connection);
04867   
04868   retval = _dbus_transport_get_socket_fd (connection->transport,
04869                                           fd);
04870 
04871   CONNECTION_UNLOCK (connection);
04872 
04873   return retval;
04874 }
04875 
04876 
04899 dbus_bool_t
04900 dbus_connection_get_unix_user (DBusConnection *connection,
04901                                unsigned long  *uid)
04902 {
04903   dbus_bool_t result;
04904 
04905   _dbus_return_val_if_fail (connection != NULL, FALSE);
04906   _dbus_return_val_if_fail (uid != NULL, FALSE);
04907   
04908   CONNECTION_LOCK (connection);
04909 
04910   if (!_dbus_transport_get_is_authenticated (connection->transport))
04911     result = FALSE;
04912   else
04913     result = _dbus_transport_get_unix_user (connection->transport,
04914                                             uid);
04915 
04916 #ifdef DBUS_WIN
04917   _dbus_assert (!result);
04918 #endif
04919   
04920   CONNECTION_UNLOCK (connection);
04921 
04922   return result;
04923 }
04924 
04935 dbus_bool_t
04936 dbus_connection_get_unix_process_id (DBusConnection *connection,
04937                                      unsigned long  *pid)
04938 {
04939   dbus_bool_t result;
04940 
04941   _dbus_return_val_if_fail (connection != NULL, FALSE);
04942   _dbus_return_val_if_fail (pid != NULL, FALSE);
04943   
04944   CONNECTION_LOCK (connection);
04945 
04946   if (!_dbus_transport_get_is_authenticated (connection->transport))
04947     result = FALSE;
04948   else
04949     result = _dbus_transport_get_unix_process_id (connection->transport,
04950                                                   pid);
04951 #ifdef DBUS_WIN
04952   _dbus_assert (!result);
04953 #endif
04954   
04955   CONNECTION_UNLOCK (connection);
04956 
04957   return result;
04958 }
04959 
04982 void
04983 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04984                                         DBusAllowUnixUserFunction   function,
04985                                         void                       *data,
04986                                         DBusFreeFunction            free_data_function)
04987 {
04988   void *old_data = NULL;
04989   DBusFreeFunction old_free_function = NULL;
04990 
04991   _dbus_return_if_fail (connection != NULL);
04992   
04993   CONNECTION_LOCK (connection);
04994   _dbus_transport_set_unix_user_function (connection->transport,
04995                                           function, data, free_data_function,
04996                                           &old_data, &old_free_function);
04997   CONNECTION_UNLOCK (connection);
04998 
04999   if (old_free_function != NULL)
05000     (* old_free_function) (old_data);
05001 }
05002 
05034 dbus_bool_t
05035 dbus_connection_get_windows_user (DBusConnection             *connection,
05036                                   char                      **windows_sid_p)
05037 {
05038   dbus_bool_t result;
05039 
05040   _dbus_return_val_if_fail (connection != NULL, FALSE);
05041   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05042   
05043   CONNECTION_LOCK (connection);
05044 
05045   if (!_dbus_transport_get_is_authenticated (connection->transport))
05046     result = FALSE;
05047   else
05048     result = _dbus_transport_get_windows_user (connection->transport,
05049                                                windows_sid_p);
05050 
05051 #ifdef DBUS_UNIX
05052   _dbus_assert (!result);
05053 #endif
05054   
05055   CONNECTION_UNLOCK (connection);
05056 
05057   return result;
05058 }
05059 
05081 void
05082 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05083                                            DBusAllowWindowsUserFunction function,
05084                                            void                        *data,
05085                                            DBusFreeFunction             free_data_function)
05086 {
05087   void *old_data = NULL;
05088   DBusFreeFunction old_free_function = NULL;
05089 
05090   _dbus_return_if_fail (connection != NULL);
05091   
05092   CONNECTION_LOCK (connection);
05093   _dbus_transport_set_windows_user_function (connection->transport,
05094                                              function, data, free_data_function,
05095                                              &old_data, &old_free_function);
05096   CONNECTION_UNLOCK (connection);
05097 
05098   if (old_free_function != NULL)
05099     (* old_free_function) (old_data);
05100 }
05101 
05128 void
05129 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05130                                      dbus_bool_t                 value)
05131 {
05132   _dbus_return_if_fail (connection != NULL);
05133   
05134   CONNECTION_LOCK (connection);
05135   _dbus_transport_set_allow_anonymous (connection->transport, value);
05136   CONNECTION_UNLOCK (connection);
05137 }
05138 
05156 void
05157 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05158                                          dbus_bool_t                 value)
05159 {
05160   _dbus_return_if_fail (connection != NULL);
05161   
05162   CONNECTION_LOCK (connection);
05163   connection->route_peer_messages = TRUE;
05164   CONNECTION_UNLOCK (connection);
05165 }
05166 
05188 dbus_bool_t
05189 dbus_connection_add_filter (DBusConnection            *connection,
05190                             DBusHandleMessageFunction  function,
05191                             void                      *user_data,
05192                             DBusFreeFunction           free_data_function)
05193 {
05194   DBusMessageFilter *filter;
05195   
05196   _dbus_return_val_if_fail (connection != NULL, FALSE);
05197   _dbus_return_val_if_fail (function != NULL, FALSE);
05198 
05199   filter = dbus_new0 (DBusMessageFilter, 1);
05200   if (filter == NULL)
05201     return FALSE;
05202 
05203   filter->refcount.value = 1;
05204   
05205   CONNECTION_LOCK (connection);
05206 
05207   if (!_dbus_list_append (&connection->filter_list,
05208                           filter))
05209     {
05210       _dbus_message_filter_unref (filter);
05211       CONNECTION_UNLOCK (connection);
05212       return FALSE;
05213     }
05214 
05215   /* Fill in filter after all memory allocated,
05216    * so we don't run the free_user_data_function
05217    * if the add_filter() fails
05218    */
05219   
05220   filter->function = function;
05221   filter->user_data = user_data;
05222   filter->free_user_data_function = free_data_function;
05223         
05224   CONNECTION_UNLOCK (connection);
05225   return TRUE;
05226 }
05227 
05240 void
05241 dbus_connection_remove_filter (DBusConnection            *connection,
05242                                DBusHandleMessageFunction  function,
05243                                void                      *user_data)
05244 {
05245   DBusList *link;
05246   DBusMessageFilter *filter;
05247   
05248   _dbus_return_if_fail (connection != NULL);
05249   _dbus_return_if_fail (function != NULL);
05250   
05251   CONNECTION_LOCK (connection);
05252 
05253   filter = NULL;
05254   
05255   link = _dbus_list_get_last_link (&connection->filter_list);
05256   while (link != NULL)
05257     {
05258       filter = link->data;
05259 
05260       if (filter->function == function &&
05261           filter->user_data == user_data)
05262         {
05263           _dbus_list_remove_link (&connection->filter_list, link);
05264           filter->function = NULL;
05265           
05266           break;
05267         }
05268         
05269       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05270     }
05271   
05272   CONNECTION_UNLOCK (connection);
05273 
05274 #ifndef DBUS_DISABLE_CHECKS
05275   if (filter == NULL)
05276     {
05277       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05278                                function, user_data);
05279       return;
05280     }
05281 #endif
05282   
05283   /* Call application code */
05284   if (filter->free_user_data_function)
05285     (* filter->free_user_data_function) (filter->user_data);
05286 
05287   filter->free_user_data_function = NULL;
05288   filter->user_data = NULL;
05289   
05290   _dbus_message_filter_unref (filter);
05291 }
05292 
05305 dbus_bool_t
05306 dbus_connection_try_register_object_path (DBusConnection              *connection,
05307                                           const char                  *path,
05308                                           const DBusObjectPathVTable  *vtable,
05309                                           void                        *user_data,
05310                                           DBusError                   *error)
05311 {
05312   char **decomposed_path;
05313   dbus_bool_t retval;
05314   
05315   _dbus_return_val_if_fail (connection != NULL, FALSE);
05316   _dbus_return_val_if_fail (path != NULL, FALSE);
05317   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05318   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05319 
05320   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05321     return FALSE;
05322 
05323   CONNECTION_LOCK (connection);
05324 
05325   retval = _dbus_object_tree_register (connection->objects,
05326                                        FALSE,
05327                                        (const char **) decomposed_path, vtable,
05328                                        user_data, error);
05329 
05330   CONNECTION_UNLOCK (connection);
05331 
05332   dbus_free_string_array (decomposed_path);
05333 
05334   return retval;
05335 }
05336 
05351 dbus_bool_t
05352 dbus_connection_register_object_path (DBusConnection              *connection,
05353                                       const char                  *path,
05354                                       const DBusObjectPathVTable  *vtable,
05355                                       void                        *user_data)
05356 {
05357   char **decomposed_path;
05358   dbus_bool_t retval;
05359   DBusError error = DBUS_ERROR_INIT;
05360 
05361   _dbus_return_val_if_fail (connection != NULL, FALSE);
05362   _dbus_return_val_if_fail (path != NULL, FALSE);
05363   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05364   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05365 
05366   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05367     return FALSE;
05368 
05369   CONNECTION_LOCK (connection);
05370 
05371   retval = _dbus_object_tree_register (connection->objects,
05372                                        FALSE,
05373                                        (const char **) decomposed_path, vtable,
05374                                        user_data, &error);
05375 
05376   CONNECTION_UNLOCK (connection);
05377 
05378   dbus_free_string_array (decomposed_path);
05379 
05380   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05381     {
05382       _dbus_warn ("%s\n", error.message);
05383       dbus_error_free (&error);
05384       return FALSE;
05385     }
05386 
05387   return retval;
05388 }
05389 
05404 dbus_bool_t
05405 dbus_connection_try_register_fallback (DBusConnection              *connection,
05406                                        const char                  *path,
05407                                        const DBusObjectPathVTable  *vtable,
05408                                        void                        *user_data,
05409                                        DBusError                   *error)
05410 {
05411   char **decomposed_path;
05412   dbus_bool_t retval;
05413 
05414   _dbus_return_val_if_fail (connection != NULL, FALSE);
05415   _dbus_return_val_if_fail (path != NULL, FALSE);
05416   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05417   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05418 
05419   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05420     return FALSE;
05421 
05422   CONNECTION_LOCK (connection);
05423 
05424   retval = _dbus_object_tree_register (connection->objects,
05425                                        TRUE,
05426                                        (const char **) decomposed_path, vtable,
05427                                        user_data, error);
05428 
05429   CONNECTION_UNLOCK (connection);
05430 
05431   dbus_free_string_array (decomposed_path);
05432 
05433   return retval;
05434 }
05435 
05452 dbus_bool_t
05453 dbus_connection_register_fallback (DBusConnection              *connection,
05454                                    const char                  *path,
05455                                    const DBusObjectPathVTable  *vtable,
05456                                    void                        *user_data)
05457 {
05458   char **decomposed_path;
05459   dbus_bool_t retval;
05460   DBusError error = DBUS_ERROR_INIT;
05461 
05462   _dbus_return_val_if_fail (connection != NULL, FALSE);
05463   _dbus_return_val_if_fail (path != NULL, FALSE);
05464   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05465   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05466 
05467   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05468     return FALSE;
05469 
05470   CONNECTION_LOCK (connection);
05471 
05472   retval = _dbus_object_tree_register (connection->objects,
05473                                        TRUE,
05474                                        (const char **) decomposed_path, vtable,
05475                                        user_data, &error);
05476 
05477   CONNECTION_UNLOCK (connection);
05478 
05479   dbus_free_string_array (decomposed_path);
05480 
05481   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05482     {
05483       _dbus_warn ("%s\n", error.message);
05484       dbus_error_free (&error);
05485       return FALSE;
05486     }
05487 
05488   return retval;
05489 }
05490 
05500 dbus_bool_t
05501 dbus_connection_unregister_object_path (DBusConnection              *connection,
05502                                         const char                  *path)
05503 {
05504   char **decomposed_path;
05505 
05506   _dbus_return_val_if_fail (connection != NULL, FALSE);
05507   _dbus_return_val_if_fail (path != NULL, FALSE);
05508   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05509 
05510   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05511       return FALSE;
05512 
05513   CONNECTION_LOCK (connection);
05514 
05515   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05516 
05517   dbus_free_string_array (decomposed_path);
05518 
05519   return TRUE;
05520 }
05521 
05532 dbus_bool_t
05533 dbus_connection_get_object_path_data (DBusConnection *connection,
05534                                       const char     *path,
05535                                       void          **data_p)
05536 {
05537   char **decomposed_path;
05538 
05539   _dbus_return_val_if_fail (connection != NULL, FALSE);
05540   _dbus_return_val_if_fail (path != NULL, FALSE);
05541   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05542 
05543   *data_p = NULL;
05544   
05545   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05546     return FALSE;
05547   
05548   CONNECTION_LOCK (connection);
05549 
05550   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05551 
05552   CONNECTION_UNLOCK (connection);
05553 
05554   dbus_free_string_array (decomposed_path);
05555 
05556   return TRUE;
05557 }
05558 
05569 dbus_bool_t
05570 dbus_connection_list_registered (DBusConnection              *connection,
05571                                  const char                  *parent_path,
05572                                  char                      ***child_entries)
05573 {
05574   char **decomposed_path;
05575   dbus_bool_t retval;
05576   _dbus_return_val_if_fail (connection != NULL, FALSE);
05577   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05578   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05579   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05580 
05581   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05582     return FALSE;
05583 
05584   CONNECTION_LOCK (connection);
05585 
05586   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05587                                                          (const char **) decomposed_path,
05588                                                          child_entries);
05589   dbus_free_string_array (decomposed_path);
05590 
05591   return retval;
05592 }
05593 
05594 static DBusDataSlotAllocator slot_allocator;
05595 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05596 
05611 dbus_bool_t
05612 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05613 {
05614   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05615                                           &_DBUS_LOCK_NAME (connection_slots),
05616                                           slot_p);
05617 }
05618 
05630 void
05631 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05632 {
05633   _dbus_return_if_fail (*slot_p >= 0);
05634   
05635   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05636 }
05637 
05651 dbus_bool_t
05652 dbus_connection_set_data (DBusConnection   *connection,
05653                           dbus_int32_t      slot,
05654                           void             *data,
05655                           DBusFreeFunction  free_data_func)
05656 {
05657   DBusFreeFunction old_free_func;
05658   void *old_data;
05659   dbus_bool_t retval;
05660 
05661   _dbus_return_val_if_fail (connection != NULL, FALSE);
05662   _dbus_return_val_if_fail (slot >= 0, FALSE);
05663   
05664   CONNECTION_LOCK (connection);
05665 
05666   retval = _dbus_data_slot_list_set (&slot_allocator,
05667                                      &connection->slot_list,
05668                                      slot, data, free_data_func,
05669                                      &old_free_func, &old_data);
05670   
05671   CONNECTION_UNLOCK (connection);
05672 
05673   if (retval)
05674     {
05675       /* Do the actual free outside the connection lock */
05676       if (old_free_func)
05677         (* old_free_func) (old_data);
05678     }
05679 
05680   return retval;
05681 }
05682 
05691 void*
05692 dbus_connection_get_data (DBusConnection   *connection,
05693                           dbus_int32_t      slot)
05694 {
05695   void *res;
05696 
05697   _dbus_return_val_if_fail (connection != NULL, NULL);
05698   
05699   CONNECTION_LOCK (connection);
05700 
05701   res = _dbus_data_slot_list_get (&slot_allocator,
05702                                   &connection->slot_list,
05703                                   slot);
05704   
05705   CONNECTION_UNLOCK (connection);
05706 
05707   return res;
05708 }
05709 
05716 void
05717 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05718 {  
05719   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05720 }
05721 
05730 void
05731 dbus_connection_set_max_message_size (DBusConnection *connection,
05732                                       long            size)
05733 {
05734   _dbus_return_if_fail (connection != NULL);
05735   
05736   CONNECTION_LOCK (connection);
05737   _dbus_transport_set_max_message_size (connection->transport,
05738                                         size);
05739   CONNECTION_UNLOCK (connection);
05740 }
05741 
05748 long
05749 dbus_connection_get_max_message_size (DBusConnection *connection)
05750 {
05751   long res;
05752 
05753   _dbus_return_val_if_fail (connection != NULL, 0);
05754   
05755   CONNECTION_LOCK (connection);
05756   res = _dbus_transport_get_max_message_size (connection->transport);
05757   CONNECTION_UNLOCK (connection);
05758   return res;
05759 }
05760 
05786 void
05787 dbus_connection_set_max_received_size (DBusConnection *connection,
05788                                        long            size)
05789 {
05790   _dbus_return_if_fail (connection != NULL);
05791   
05792   CONNECTION_LOCK (connection);
05793   _dbus_transport_set_max_received_size (connection->transport,
05794                                          size);
05795   CONNECTION_UNLOCK (connection);
05796 }
05797 
05804 long
05805 dbus_connection_get_max_received_size (DBusConnection *connection)
05806 {
05807   long res;
05808 
05809   _dbus_return_val_if_fail (connection != NULL, 0);
05810   
05811   CONNECTION_LOCK (connection);
05812   res = _dbus_transport_get_max_received_size (connection->transport);
05813   CONNECTION_UNLOCK (connection);
05814   return res;
05815 }
05816 
05827 long
05828 dbus_connection_get_outgoing_size (DBusConnection *connection)
05829 {
05830   long res;
05831 
05832   _dbus_return_val_if_fail (connection != NULL, 0);
05833   
05834   CONNECTION_LOCK (connection);
05835   res = _dbus_counter_get_value (connection->outgoing_counter);
05836   CONNECTION_UNLOCK (connection);
05837   return res;
05838 }
05839 

Generated on Sat Jun 14 22:43:03 2008 for D-Bus by  doxygen 1.4.6