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   int 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 
01442 static void
01443 shared_connections_shutdown (void *data)
01444 {
01445   int n_entries;
01446   
01447   _DBUS_LOCK (shared_connections);
01448   
01449   /* This is a little bit unpleasant... better ideas? */
01450   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01451     {
01452       DBusConnection *connection;
01453       DBusMessage *message;
01454       DBusHashIter iter;
01455       
01456       _dbus_hash_iter_init (shared_connections, &iter);
01457       _dbus_hash_iter_next (&iter);
01458        
01459       connection = _dbus_hash_iter_get_value (&iter);
01460 
01461       _DBUS_UNLOCK (shared_connections);
01462 
01463       dbus_connection_ref (connection);
01464       _dbus_connection_close_possibly_shared (connection);
01465 
01466       /* Churn through to the Disconnected message */
01467       while ((message = dbus_connection_pop_message (connection)))
01468         {
01469           dbus_message_unref (message);
01470         }
01471       dbus_connection_unref (connection);
01472       
01473       _DBUS_LOCK (shared_connections);
01474 
01475       /* The connection should now be dead and not in our hash ... */
01476       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01477     }
01478 
01479   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01480   
01481   _dbus_hash_table_unref (shared_connections);
01482   shared_connections = NULL;
01483   
01484   _DBUS_UNLOCK (shared_connections);
01485 }
01486 
01487 static dbus_bool_t
01488 connection_lookup_shared (DBusAddressEntry  *entry,
01489                           DBusConnection   **result)
01490 {
01491   _dbus_verbose ("checking for existing connection\n");
01492   
01493   *result = NULL;
01494   
01495   _DBUS_LOCK (shared_connections);
01496 
01497   if (shared_connections == NULL)
01498     {
01499       _dbus_verbose ("creating shared_connections hash table\n");
01500       
01501       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01502                                                  dbus_free,
01503                                                  NULL);
01504       if (shared_connections == NULL)
01505         {
01506           _DBUS_UNLOCK (shared_connections);
01507           return FALSE;
01508         }
01509 
01510       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01511         {
01512           _dbus_hash_table_unref (shared_connections);
01513           shared_connections = NULL;
01514           _DBUS_UNLOCK (shared_connections);
01515           return FALSE;
01516         }
01517 
01518       _dbus_verbose ("  successfully created shared_connections\n");
01519       
01520       _DBUS_UNLOCK (shared_connections);
01521       return TRUE; /* no point looking up in the hash we just made */
01522     }
01523   else
01524     {
01525       const char *guid;
01526 
01527       guid = dbus_address_entry_get_value (entry, "guid");
01528       
01529       if (guid != NULL)
01530         {
01531           DBusConnection *connection;
01532           
01533           connection = _dbus_hash_table_lookup_string (shared_connections,
01534                                                        guid);
01535 
01536           if (connection)
01537             {
01538               /* The DBusConnection can't be finalized without taking
01539                * the shared_connections lock to remove it from the
01540                * hash.  So it's safe to ref the connection here.
01541                * However, it may be disconnected if the Disconnected
01542                * message hasn't been processed yet, in which case we
01543                * want to pretend it isn't in the hash and avoid
01544                * returning it.
01545                *
01546                * The idea is to avoid ever returning a disconnected connection
01547                * from dbus_connection_open(). We could just synchronously
01548                * drop our shared ref to the connection on connection disconnect,
01549                * and then assert here that the connection is connected, but
01550                * that causes reentrancy headaches.
01551                */
01552               CONNECTION_LOCK (connection);
01553               if (_dbus_connection_get_is_connected_unlocked (connection))
01554                 {
01555                   _dbus_connection_ref_unlocked (connection);
01556                   *result = connection;
01557                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01558                                  guid);
01559                 }
01560               else
01561                 {
01562                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01563                                  guid);
01564                 }
01565               CONNECTION_UNLOCK (connection);
01566             }
01567         }
01568       
01569       _DBUS_UNLOCK (shared_connections);
01570       return TRUE;
01571     }
01572 }
01573 
01574 static dbus_bool_t
01575 connection_record_shared_unlocked (DBusConnection *connection,
01576                                    const char     *guid)
01577 {
01578   char *guid_key;
01579   char *guid_in_connection;
01580 
01581   HAVE_LOCK_CHECK (connection);
01582   _dbus_assert (connection->server_guid == NULL);
01583   _dbus_assert (connection->shareable);
01584 
01585   /* get a hard ref on this connection, even if
01586    * we won't in fact store it in the hash, we still
01587    * need to hold a ref on it until it's disconnected.
01588    */
01589   _dbus_connection_ref_unlocked (connection);
01590 
01591   if (guid == NULL)
01592     return TRUE; /* don't store in the hash */
01593   
01594   /* A separate copy of the key is required in the hash table, because
01595    * we don't have a lock on the connection when we are doing a hash
01596    * lookup.
01597    */
01598   
01599   guid_key = _dbus_strdup (guid);
01600   if (guid_key == NULL)
01601     return FALSE;
01602 
01603   guid_in_connection = _dbus_strdup (guid);
01604   if (guid_in_connection == NULL)
01605     {
01606       dbus_free (guid_key);
01607       return FALSE;
01608     }
01609   
01610   _DBUS_LOCK (shared_connections);
01611   _dbus_assert (shared_connections != NULL);
01612   
01613   if (!_dbus_hash_table_insert_string (shared_connections,
01614                                        guid_key, connection))
01615     {
01616       dbus_free (guid_key);
01617       dbus_free (guid_in_connection);
01618       _DBUS_UNLOCK (shared_connections);
01619       return FALSE;
01620     }
01621 
01622   connection->server_guid = guid_in_connection;
01623 
01624   _dbus_verbose ("stored connection to %s to be shared\n",
01625                  connection->server_guid);
01626   
01627   _DBUS_UNLOCK (shared_connections);
01628 
01629   _dbus_assert (connection->server_guid != NULL);
01630   
01631   return TRUE;
01632 }
01633 
01634 static void
01635 connection_forget_shared_unlocked (DBusConnection *connection)
01636 {
01637   HAVE_LOCK_CHECK (connection);
01638 
01639   if (!connection->shareable)
01640     return;
01641   
01642   if (connection->server_guid != NULL)
01643     {
01644       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01645                      connection->server_guid);
01646       
01647       _DBUS_LOCK (shared_connections);
01648       
01649       if (!_dbus_hash_table_remove_string (shared_connections,
01650                                            connection->server_guid))
01651         _dbus_assert_not_reached ("connection was not in the shared table");
01652       
01653       dbus_free (connection->server_guid);
01654       connection->server_guid = NULL;
01655       _DBUS_UNLOCK (shared_connections);
01656     }
01657   
01658   /* remove our reference held on all shareable connections */
01659   _dbus_connection_unref_unlocked (connection);
01660 }
01661 
01662 static DBusConnection*
01663 connection_try_from_address_entry (DBusAddressEntry *entry,
01664                                    DBusError        *error)
01665 {
01666   DBusTransport *transport;
01667   DBusConnection *connection;
01668 
01669   transport = _dbus_transport_open (entry, error);
01670 
01671   if (transport == NULL)
01672     {
01673       _DBUS_ASSERT_ERROR_IS_SET (error);
01674       return NULL;
01675     }
01676 
01677   connection = _dbus_connection_new_for_transport (transport);
01678 
01679   _dbus_transport_unref (transport);
01680   
01681   if (connection == NULL)
01682     {
01683       _DBUS_SET_OOM (error);
01684       return NULL;
01685     }
01686 
01687 #ifndef DBUS_DISABLE_CHECKS
01688   _dbus_assert (!connection->have_connection_lock);
01689 #endif
01690   return connection;
01691 }
01692 
01693 /*
01694  * If the shared parameter is true, then any existing connection will
01695  * be used (and if a new connection is created, it will be available
01696  * for use by others). If the shared parameter is false, a new
01697  * connection will always be created, and the new connection will
01698  * never be returned to other callers.
01699  *
01700  * @param address the address
01701  * @param shared whether the connection is shared or private
01702  * @param error error return
01703  * @returns the connection or #NULL on error
01704  */
01705 static DBusConnection*
01706 _dbus_connection_open_internal (const char     *address,
01707                                 dbus_bool_t     shared,
01708                                 DBusError      *error)
01709 {
01710   DBusConnection *connection;
01711   DBusAddressEntry **entries;
01712   DBusError tmp_error;
01713   DBusError first_error;
01714   int len, i;
01715 
01716   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01717 
01718   _dbus_verbose ("opening %s connection to: %s\n",
01719                  shared ? "shared" : "private", address);
01720   
01721   if (!dbus_parse_address (address, &entries, &len, error))
01722     return NULL;
01723 
01724   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01725   
01726   connection = NULL;
01727 
01728   dbus_error_init (&tmp_error);
01729   dbus_error_init (&first_error);
01730   for (i = 0; i < len; i++)
01731     {
01732       if (shared)
01733         {
01734           if (!connection_lookup_shared (entries[i], &connection))
01735             _DBUS_SET_OOM (&tmp_error);
01736         }
01737 
01738       if (connection == NULL)
01739         {
01740           connection = connection_try_from_address_entry (entries[i],
01741                                                           &tmp_error);
01742 
01743           if (connection != NULL && shared)
01744             {
01745               const char *guid;
01746                   
01747               connection->shareable = TRUE;
01748                   
01749               /* guid may be NULL */
01750               guid = dbus_address_entry_get_value (entries[i], "guid");
01751                   
01752               CONNECTION_LOCK (connection);
01753           
01754               if (!connection_record_shared_unlocked (connection, guid))
01755                 {
01756                   _DBUS_SET_OOM (&tmp_error);
01757                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01758                   dbus_connection_unref (connection);
01759                   connection = NULL;
01760                 }
01761               else
01762                 CONNECTION_UNLOCK (connection);
01763             }
01764         }
01765       
01766       if (connection)
01767         break;
01768 
01769       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01770       
01771       if (i == 0)
01772         dbus_move_error (&tmp_error, &first_error);
01773       else
01774         dbus_error_free (&tmp_error);
01775     }
01776   
01777   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01778   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01779   
01780   if (connection == NULL)
01781     {
01782       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01783       dbus_move_error (&first_error, error);
01784     }
01785   else
01786     dbus_error_free (&first_error);
01787   
01788   dbus_address_entries_free (entries);
01789   return connection;
01790 }
01791 
01800 void
01801 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01802 {
01803   _dbus_assert (connection != NULL);
01804   _dbus_assert (connection->generation == _dbus_current_generation);
01805 
01806   CONNECTION_LOCK (connection);
01807   _dbus_connection_close_possibly_shared_and_unlock (connection);
01808 }
01809 
01810 static DBusPreallocatedSend*
01811 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01812 {
01813   DBusPreallocatedSend *preallocated;
01814 
01815   HAVE_LOCK_CHECK (connection);
01816   
01817   _dbus_assert (connection != NULL);
01818   
01819   preallocated = dbus_new (DBusPreallocatedSend, 1);
01820   if (preallocated == NULL)
01821     return NULL;
01822 
01823   if (connection->link_cache != NULL)
01824     {
01825       preallocated->queue_link =
01826         _dbus_list_pop_first_link (&connection->link_cache);
01827       preallocated->queue_link->data = NULL;
01828     }
01829   else
01830     {
01831       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01832       if (preallocated->queue_link == NULL)
01833         goto failed_0;
01834     }
01835   
01836   if (connection->link_cache != NULL)
01837     {
01838       preallocated->counter_link =
01839         _dbus_list_pop_first_link (&connection->link_cache);
01840       preallocated->counter_link->data = connection->outgoing_counter;
01841     }
01842   else
01843     {
01844       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01845       if (preallocated->counter_link == NULL)
01846         goto failed_1;
01847     }
01848 
01849   _dbus_counter_ref (preallocated->counter_link->data);
01850 
01851   preallocated->connection = connection;
01852   
01853   return preallocated;
01854   
01855  failed_1:
01856   _dbus_list_free_link (preallocated->queue_link);
01857  failed_0:
01858   dbus_free (preallocated);
01859   
01860   return NULL;
01861 }
01862 
01863 /* Called with lock held, does not update dispatch status */
01864 static void
01865 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01866                                                        DBusPreallocatedSend *preallocated,
01867                                                        DBusMessage          *message,
01868                                                        dbus_uint32_t        *client_serial)
01869 {
01870   dbus_uint32_t serial;
01871   const char *sig;
01872 
01873   preallocated->queue_link->data = message;
01874   _dbus_list_prepend_link (&connection->outgoing_messages,
01875                            preallocated->queue_link);
01876 
01877   _dbus_message_add_size_counter_link (message,
01878                                        preallocated->counter_link);
01879 
01880   dbus_free (preallocated);
01881   preallocated = NULL;
01882   
01883   dbus_message_ref (message);
01884   
01885   connection->n_outgoing += 1;
01886 
01887   sig = dbus_message_get_signature (message);
01888   
01889   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01890                  message,
01891                  dbus_message_get_type (message),
01892                  dbus_message_get_path (message) ?
01893                  dbus_message_get_path (message) :
01894                  "no path",
01895                  dbus_message_get_interface (message) ?
01896                  dbus_message_get_interface (message) :
01897                  "no interface",
01898                  dbus_message_get_member (message) ?
01899                  dbus_message_get_member (message) :
01900                  "no member",
01901                  sig,
01902                  dbus_message_get_destination (message) ?
01903                  dbus_message_get_destination (message) :
01904                  "null",
01905                  connection,
01906                  connection->n_outgoing);
01907 
01908   if (dbus_message_get_serial (message) == 0)
01909     {
01910       serial = _dbus_connection_get_next_client_serial (connection);
01911       _dbus_message_set_serial (message, serial);
01912       if (client_serial)
01913         *client_serial = serial;
01914     }
01915   else
01916     {
01917       if (client_serial)
01918         *client_serial = dbus_message_get_serial (message);
01919     }
01920 
01921   _dbus_verbose ("Message %p serial is %u\n",
01922                  message, dbus_message_get_serial (message));
01923   
01924   _dbus_message_lock (message);
01925 
01926   /* Now we need to run an iteration to hopefully just write the messages
01927    * out immediately, and otherwise get them queued up
01928    */
01929   _dbus_connection_do_iteration_unlocked (connection,
01930                                           DBUS_ITERATION_DO_WRITING,
01931                                           -1);
01932 
01933   /* If stuff is still queued up, be sure we wake up the main loop */
01934   if (connection->n_outgoing > 0)
01935     _dbus_connection_wakeup_mainloop (connection);
01936 }
01937 
01938 static void
01939 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
01940                                                DBusPreallocatedSend *preallocated,
01941                                                DBusMessage          *message,
01942                                                dbus_uint32_t        *client_serial)
01943 {
01944   DBusDispatchStatus status;
01945 
01946   HAVE_LOCK_CHECK (connection);
01947   
01948   _dbus_connection_send_preallocated_unlocked_no_update (connection,
01949                                                          preallocated,
01950                                                          message, client_serial);
01951 
01952   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01953   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01954 
01955   /* this calls out to user code */
01956   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01957 }
01958 
01968 dbus_bool_t
01969 _dbus_connection_send_and_unlock (DBusConnection *connection,
01970                                   DBusMessage    *message,
01971                                   dbus_uint32_t  *client_serial)
01972 {
01973   DBusPreallocatedSend *preallocated;
01974 
01975   _dbus_assert (connection != NULL);
01976   _dbus_assert (message != NULL);
01977   
01978   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01979   if (preallocated == NULL)
01980     {
01981       CONNECTION_UNLOCK (connection);
01982       return FALSE;
01983     }
01984 
01985   _dbus_connection_send_preallocated_and_unlock (connection,
01986                                                  preallocated,
01987                                                  message,
01988                                                  client_serial);
01989   return TRUE;
01990 }
01991 
02016 void
02017 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02018 {
02019   CONNECTION_LOCK (connection);
02020   
02021   _dbus_assert (connection->refcount.value > 0);
02022 
02023   if (connection->refcount.value == 1)
02024     _dbus_connection_close_possibly_shared_and_unlock (connection);
02025   else
02026     CONNECTION_UNLOCK (connection);
02027 }
02028 
02029 
02039 static void
02040 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02041 {
02042   if (timeout_milliseconds == -1)
02043     _dbus_sleep_milliseconds (1000);
02044   else if (timeout_milliseconds < 100)
02045     ; /* just busy loop */
02046   else if (timeout_milliseconds <= 1000)
02047     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02048   else
02049     _dbus_sleep_milliseconds (1000);
02050 }
02051 
02052 static DBusMessage *
02053 generate_local_error_message (dbus_uint32_t serial, 
02054                               char *error_name, 
02055                               char *error_msg)
02056 {
02057   DBusMessage *message;
02058   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02059   if (!message)
02060     goto out;
02061 
02062   if (!dbus_message_set_error_name (message, error_name))
02063     {
02064       dbus_message_unref (message);
02065       message = NULL;
02066       goto out; 
02067     }
02068 
02069   dbus_message_set_no_reply (message, TRUE); 
02070 
02071   if (!dbus_message_set_reply_serial (message,
02072                                       serial))
02073     {
02074       dbus_message_unref (message);
02075       message = NULL;
02076       goto out;
02077     }
02078 
02079   if (error_msg != NULL)
02080     {
02081       DBusMessageIter iter;
02082 
02083       dbus_message_iter_init_append (message, &iter);
02084       if (!dbus_message_iter_append_basic (&iter,
02085                                            DBUS_TYPE_STRING,
02086                                            &error_msg))
02087         {
02088           dbus_message_unref (message);
02089           message = NULL;
02090           goto out;
02091         }
02092     }
02093 
02094  out:
02095   return message;
02096 }
02097 
02098 
02099 /* This is slightly strange since we can pop a message here without
02100  * the dispatch lock.
02101  */
02102 static DBusMessage*
02103 check_for_reply_unlocked (DBusConnection *connection,
02104                           dbus_uint32_t   client_serial)
02105 {
02106   DBusList *link;
02107 
02108   HAVE_LOCK_CHECK (connection);
02109   
02110   link = _dbus_list_get_first_link (&connection->incoming_messages);
02111 
02112   while (link != NULL)
02113     {
02114       DBusMessage *reply = link->data;
02115 
02116       if (dbus_message_get_reply_serial (reply) == client_serial)
02117         {
02118           _dbus_list_remove_link (&connection->incoming_messages, link);
02119           connection->n_incoming  -= 1;
02120           return reply;
02121         }
02122       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02123     }
02124 
02125   return NULL;
02126 }
02127 
02128 static void
02129 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02130 {
02131    /* We can't iterate over the hash in the normal way since we'll be
02132     * dropping the lock for each item. So we restart the
02133     * iter each time as we drain the hash table.
02134     */
02135    
02136    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02137     {
02138       DBusPendingCall *pending;
02139       DBusHashIter iter;
02140       
02141       _dbus_hash_iter_init (connection->pending_replies, &iter);
02142       _dbus_hash_iter_next (&iter);
02143        
02144       pending = _dbus_hash_iter_get_value (&iter);
02145       _dbus_pending_call_ref_unlocked (pending);
02146        
02147       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02148                                                        connection);
02149       _dbus_connection_remove_timeout_unlocked (connection,
02150                                                 _dbus_pending_call_get_timeout_unlocked (pending));
02151       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02152       _dbus_hash_iter_remove_entry (&iter);
02153 
02154       _dbus_pending_call_unref_and_unlock (pending);
02155       CONNECTION_LOCK (connection);
02156     }
02157   HAVE_LOCK_CHECK (connection);
02158 }
02159 
02160 static void
02161 complete_pending_call_and_unlock (DBusConnection  *connection,
02162                                   DBusPendingCall *pending,
02163                                   DBusMessage     *message)
02164 {
02165   _dbus_pending_call_set_reply_unlocked (pending, message);
02166   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02167   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02168  
02169   /* Must be called unlocked since it invokes app callback */
02170   _dbus_pending_call_complete (pending);
02171   dbus_pending_call_unref (pending);
02172 }
02173 
02174 static dbus_bool_t
02175 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02176                                               DBusPendingCall *pending)
02177 {
02178   DBusMessage *reply;
02179   DBusDispatchStatus status;
02180 
02181   reply = check_for_reply_unlocked (connection, 
02182                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02183   if (reply != NULL)
02184     {
02185       _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02186 
02187       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02188 
02189       complete_pending_call_and_unlock (connection, pending, reply);
02190       dbus_message_unref (reply);
02191 
02192       CONNECTION_LOCK (connection);
02193       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02194       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02195       dbus_pending_call_unref (pending);
02196 
02197       return TRUE;
02198     }
02199 
02200   return FALSE;
02201 }
02202 
02217 void
02218 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02219 {
02220   long start_tv_sec, start_tv_usec;
02221   long end_tv_sec, end_tv_usec;
02222   long tv_sec, tv_usec;
02223   DBusDispatchStatus status;
02224   DBusConnection *connection;
02225   dbus_uint32_t client_serial;
02226   int timeout_milliseconds;
02227 
02228   _dbus_assert (pending != NULL);
02229 
02230   if (dbus_pending_call_get_completed (pending))
02231     return;
02232 
02233   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02234 
02235   connection = _dbus_pending_call_get_connection_and_lock (pending);
02236   
02237   /* Flush message queue - note, can affect dispatch status */
02238   _dbus_connection_flush_unlocked (connection);
02239 
02240   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02241 
02242   /* note that timeout_milliseconds is limited to a smallish value
02243    * in _dbus_pending_call_new() so overflows aren't possible
02244    * below
02245    */
02246   timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02247   
02248   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02249   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02250   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02251   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02252   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02253 
02254   _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",
02255                  timeout_milliseconds,
02256                  client_serial,
02257                  start_tv_sec, start_tv_usec,
02258                  end_tv_sec, end_tv_usec);
02259 
02260   /* check to see if we already got the data off the socket */
02261   /* from another blocked pending call */
02262   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02263     return;
02264 
02265   /* Now we wait... */
02266   /* always block at least once as we know we don't have the reply yet */
02267   _dbus_connection_do_iteration_unlocked (connection,
02268                                           DBUS_ITERATION_DO_READING |
02269                                           DBUS_ITERATION_BLOCK,
02270                                           timeout_milliseconds);
02271 
02272  recheck_status:
02273 
02274   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02275   
02276   HAVE_LOCK_CHECK (connection);
02277   
02278   /* queue messages and get status */
02279 
02280   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02281 
02282   /* the get_completed() is in case a dispatch() while we were blocking
02283    * got the reply instead of us.
02284    */
02285   if (_dbus_pending_call_get_completed_unlocked (pending))
02286     {
02287       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02288       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02289       dbus_pending_call_unref (pending);
02290       return;
02291     }
02292   
02293   if (status == DBUS_DISPATCH_DATA_REMAINS) {
02294     if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02295       return;
02296   }
02297   
02298   _dbus_get_current_time (&tv_sec, &tv_usec);
02299   
02300   if (!_dbus_connection_get_is_connected_unlocked (connection))
02301     {
02302       DBusMessage *error_msg;
02303 
02304       error_msg = generate_local_error_message (client_serial,
02305                                                 DBUS_ERROR_DISCONNECTED, 
02306                                                 "Connection was disconnected before a reply was received"); 
02307 
02308       /* on OOM error_msg is set to NULL */
02309       complete_pending_call_and_unlock (connection, pending, error_msg);
02310       dbus_pending_call_unref (pending);
02311       return;
02312     }
02313   else if (tv_sec < start_tv_sec)
02314     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02315   else if (connection->disconnect_message_link == NULL)
02316     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02317   else if (tv_sec < end_tv_sec ||
02318            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02319     {
02320       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02321         (end_tv_usec - tv_usec) / 1000;
02322       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02323       _dbus_assert (timeout_milliseconds >= 0);
02324       
02325       if (status == DBUS_DISPATCH_NEED_MEMORY)
02326         {
02327           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02328            * we may already have a reply in the buffer and just can't process
02329            * it.
02330            */
02331           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02332 
02333           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02334         }
02335       else
02336         {          
02337           /* block again, we don't have the reply buffered yet. */
02338           _dbus_connection_do_iteration_unlocked (connection,
02339                                                   DBUS_ITERATION_DO_READING |
02340                                                   DBUS_ITERATION_BLOCK,
02341                                                   timeout_milliseconds);
02342         }
02343 
02344       goto recheck_status;
02345     }
02346 
02347   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02348                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02349 
02350   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02351   
02352   /* unlock and call user code */
02353   complete_pending_call_and_unlock (connection, pending, NULL);
02354 
02355   /* update user code on dispatch status */
02356   CONNECTION_LOCK (connection);
02357   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02358   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02359   dbus_pending_call_unref (pending);
02360 }
02361 
02398 DBusConnection*
02399 dbus_connection_open (const char     *address,
02400                       DBusError      *error)
02401 {
02402   DBusConnection *connection;
02403 
02404   _dbus_return_val_if_fail (address != NULL, NULL);
02405   _dbus_return_val_if_error_is_set (error, NULL);
02406 
02407   connection = _dbus_connection_open_internal (address,
02408                                                TRUE,
02409                                                error);
02410 
02411   return connection;
02412 }
02413 
02441 DBusConnection*
02442 dbus_connection_open_private (const char     *address,
02443                               DBusError      *error)
02444 {
02445   DBusConnection *connection;
02446 
02447   _dbus_return_val_if_fail (address != NULL, NULL);
02448   _dbus_return_val_if_error_is_set (error, NULL);
02449 
02450   connection = _dbus_connection_open_internal (address,
02451                                                FALSE,
02452                                                error);
02453 
02454   return connection;
02455 }
02456 
02463 DBusConnection *
02464 dbus_connection_ref (DBusConnection *connection)
02465 {
02466   _dbus_return_val_if_fail (connection != NULL, NULL);
02467   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02468   
02469   /* The connection lock is better than the global
02470    * lock in the atomic increment fallback
02471    */
02472   
02473 #ifdef DBUS_HAVE_ATOMIC_INT
02474   _dbus_atomic_inc (&connection->refcount);
02475 #else
02476   CONNECTION_LOCK (connection);
02477   _dbus_assert (connection->refcount.value > 0);
02478 
02479   connection->refcount.value += 1;
02480   CONNECTION_UNLOCK (connection);
02481 #endif
02482 
02483   return connection;
02484 }
02485 
02486 static void
02487 free_outgoing_message (void *element,
02488                        void *data)
02489 {
02490   DBusMessage *message = element;
02491   DBusConnection *connection = data;
02492 
02493   _dbus_message_remove_size_counter (message,
02494                                      connection->outgoing_counter,
02495                                      NULL);
02496   dbus_message_unref (message);
02497 }
02498 
02499 /* This is run without the mutex held, but after the last reference
02500  * to the connection has been dropped we should have no thread-related
02501  * problems
02502  */
02503 static void
02504 _dbus_connection_last_unref (DBusConnection *connection)
02505 {
02506   DBusList *link;
02507 
02508   _dbus_verbose ("Finalizing connection %p\n", connection);
02509   
02510   _dbus_assert (connection->refcount.value == 0);
02511   
02512   /* You have to disconnect the connection before unref:ing it. Otherwise
02513    * you won't get the disconnected message.
02514    */
02515   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02516   _dbus_assert (connection->server_guid == NULL);
02517   
02518   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02519   _dbus_object_tree_free_all_unlocked (connection->objects);
02520   
02521   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02522   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02523   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02524   
02525   _dbus_watch_list_free (connection->watches);
02526   connection->watches = NULL;
02527   
02528   _dbus_timeout_list_free (connection->timeouts);
02529   connection->timeouts = NULL;
02530 
02531   _dbus_data_slot_list_free (&connection->slot_list);
02532   
02533   link = _dbus_list_get_first_link (&connection->filter_list);
02534   while (link != NULL)
02535     {
02536       DBusMessageFilter *filter = link->data;
02537       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02538 
02539       filter->function = NULL;
02540       _dbus_message_filter_unref (filter); /* calls app callback */
02541       link->data = NULL;
02542       
02543       link = next;
02544     }
02545   _dbus_list_clear (&connection->filter_list);
02546   
02547   /* ---- Done with stuff that invokes application callbacks */
02548 
02549   _dbus_object_tree_unref (connection->objects);  
02550 
02551   _dbus_hash_table_unref (connection->pending_replies);
02552   connection->pending_replies = NULL;
02553   
02554   _dbus_list_clear (&connection->filter_list);
02555   
02556   _dbus_list_foreach (&connection->outgoing_messages,
02557                       free_outgoing_message,
02558                       connection);
02559   _dbus_list_clear (&connection->outgoing_messages);
02560   
02561   _dbus_list_foreach (&connection->incoming_messages,
02562                       (DBusForeachFunction) dbus_message_unref,
02563                       NULL);
02564   _dbus_list_clear (&connection->incoming_messages);
02565 
02566   _dbus_counter_unref (connection->outgoing_counter);
02567 
02568   _dbus_transport_unref (connection->transport);
02569 
02570   if (connection->disconnect_message_link)
02571     {
02572       DBusMessage *message = connection->disconnect_message_link->data;
02573       dbus_message_unref (message);
02574       _dbus_list_free_link (connection->disconnect_message_link);
02575     }
02576 
02577   _dbus_list_clear (&connection->link_cache);
02578   
02579   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02580   _dbus_condvar_free_at_location (&connection->io_path_cond);
02581 
02582   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02583   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02584 
02585   _dbus_mutex_free_at_location (&connection->mutex);
02586   
02587   dbus_free (connection);
02588 }
02589 
02609 void
02610 dbus_connection_unref (DBusConnection *connection)
02611 {
02612   dbus_bool_t last_unref;
02613 
02614   _dbus_return_if_fail (connection != NULL);
02615   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02616   
02617   /* The connection lock is better than the global
02618    * lock in the atomic increment fallback
02619    */
02620   
02621 #ifdef DBUS_HAVE_ATOMIC_INT
02622   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02623 #else
02624   CONNECTION_LOCK (connection);
02625   
02626   _dbus_assert (connection->refcount.value > 0);
02627 
02628   connection->refcount.value -= 1;
02629   last_unref = (connection->refcount.value == 0);
02630 
02631 #if 0
02632   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02633 #endif
02634   
02635   CONNECTION_UNLOCK (connection);
02636 #endif
02637   
02638   if (last_unref)
02639     {
02640 #ifndef DBUS_DISABLE_CHECKS
02641       if (_dbus_transport_get_is_connected (connection->transport))
02642         {
02643           _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",
02644                                    connection->shareable ?
02645                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02646                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02647           return;
02648         }
02649 #endif
02650       _dbus_connection_last_unref (connection);
02651     }
02652 }
02653 
02654 /*
02655  * Note that the transport can disconnect itself (other end drops us)
02656  * and in that case this function never runs. So this function must
02657  * not do anything more than disconnect the transport and update the
02658  * dispatch status.
02659  * 
02660  * If the transport self-disconnects, then we assume someone will
02661  * dispatch the connection to cause the dispatch status update.
02662  */
02663 static void
02664 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02665 {
02666   DBusDispatchStatus status;
02667 
02668   HAVE_LOCK_CHECK (connection);
02669   
02670   _dbus_verbose ("Disconnecting %p\n", connection);
02671 
02672   /* We need to ref because update_dispatch_status_and_unlock will unref
02673    * the connection if it was shared and libdbus was the only remaining
02674    * refcount holder.
02675    */
02676   _dbus_connection_ref_unlocked (connection);
02677   
02678   _dbus_transport_disconnect (connection->transport);
02679 
02680   /* This has the side effect of queuing the disconnect message link
02681    * (unless we don't have enough memory, possibly, so don't assert it).
02682    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02683    * should never again return the newly-disconnected connection.
02684    *
02685    * However, we only unref the shared connection and exit_on_disconnect when
02686    * the disconnect message reaches the head of the message queue,
02687    * NOT when it's first queued.
02688    */
02689   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02690 
02691   /* This calls out to user code */
02692   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02693 
02694   /* Could also call out to user code */
02695   dbus_connection_unref (connection);
02696 }
02697 
02740 void
02741 dbus_connection_close (DBusConnection *connection)
02742 {
02743   _dbus_return_if_fail (connection != NULL);
02744   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02745 
02746   CONNECTION_LOCK (connection);
02747 
02748 #ifndef DBUS_DISABLE_CHECKS
02749   if (connection->shareable)
02750     {
02751       CONNECTION_UNLOCK (connection);
02752 
02753       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02754       return;
02755     }
02756 #endif
02757   
02758   _dbus_connection_close_possibly_shared_and_unlock (connection);
02759 }
02760 
02761 static dbus_bool_t
02762 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02763 {
02764   HAVE_LOCK_CHECK (connection);
02765   return _dbus_transport_get_is_connected (connection->transport);
02766 }
02767 
02781 dbus_bool_t
02782 dbus_connection_get_is_connected (DBusConnection *connection)
02783 {
02784   dbus_bool_t res;
02785 
02786   _dbus_return_val_if_fail (connection != NULL, FALSE);
02787   
02788   CONNECTION_LOCK (connection);
02789   res = _dbus_connection_get_is_connected_unlocked (connection);
02790   CONNECTION_UNLOCK (connection);
02791   
02792   return res;
02793 }
02794 
02803 dbus_bool_t
02804 dbus_connection_get_is_authenticated (DBusConnection *connection)
02805 {
02806   dbus_bool_t res;
02807 
02808   _dbus_return_val_if_fail (connection != NULL, FALSE);
02809   
02810   CONNECTION_LOCK (connection);
02811   res = _dbus_transport_get_is_authenticated (connection->transport);
02812   CONNECTION_UNLOCK (connection);
02813   
02814   return res;
02815 }
02816 
02837 dbus_bool_t
02838 dbus_connection_get_is_anonymous (DBusConnection *connection)
02839 {
02840   dbus_bool_t res;
02841 
02842   _dbus_return_val_if_fail (connection != NULL, FALSE);
02843   
02844   CONNECTION_LOCK (connection);
02845   res = _dbus_transport_get_is_anonymous (connection->transport);
02846   CONNECTION_UNLOCK (connection);
02847   
02848   return res;
02849 }
02850 
02882 char*
02883 dbus_connection_get_server_id (DBusConnection *connection)
02884 {
02885   char *id;
02886 
02887   _dbus_return_val_if_fail (connection != NULL, FALSE);
02888   
02889   CONNECTION_LOCK (connection);
02890   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02891   CONNECTION_UNLOCK (connection);
02892   
02893   return id;
02894 }
02895 
02909 void
02910 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02911                                         dbus_bool_t     exit_on_disconnect)
02912 {
02913   _dbus_return_if_fail (connection != NULL);
02914 
02915   CONNECTION_LOCK (connection);
02916   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02917   CONNECTION_UNLOCK (connection);
02918 }
02919 
02929 DBusPreallocatedSend*
02930 dbus_connection_preallocate_send (DBusConnection *connection)
02931 {
02932   DBusPreallocatedSend *preallocated;
02933 
02934   _dbus_return_val_if_fail (connection != NULL, NULL);
02935 
02936   CONNECTION_LOCK (connection);
02937   
02938   preallocated =
02939     _dbus_connection_preallocate_send_unlocked (connection);
02940 
02941   CONNECTION_UNLOCK (connection);
02942 
02943   return preallocated;
02944 }
02945 
02955 void
02956 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02957                                         DBusPreallocatedSend *preallocated)
02958 {
02959   _dbus_return_if_fail (connection != NULL);
02960   _dbus_return_if_fail (preallocated != NULL);  
02961   _dbus_return_if_fail (connection == preallocated->connection);
02962 
02963   _dbus_list_free_link (preallocated->queue_link);
02964   _dbus_counter_unref (preallocated->counter_link->data);
02965   _dbus_list_free_link (preallocated->counter_link);
02966   dbus_free (preallocated);
02967 }
02968 
02981 void
02982 dbus_connection_send_preallocated (DBusConnection       *connection,
02983                                    DBusPreallocatedSend *preallocated,
02984                                    DBusMessage          *message,
02985                                    dbus_uint32_t        *client_serial)
02986 {
02987   _dbus_return_if_fail (connection != NULL);
02988   _dbus_return_if_fail (preallocated != NULL);
02989   _dbus_return_if_fail (message != NULL);
02990   _dbus_return_if_fail (preallocated->connection == connection);
02991   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02992                         dbus_message_get_member (message) != NULL);
02993   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02994                         (dbus_message_get_interface (message) != NULL &&
02995                          dbus_message_get_member (message) != NULL));
02996   
02997   CONNECTION_LOCK (connection);
02998   _dbus_connection_send_preallocated_and_unlock (connection,
02999                                                  preallocated,
03000                                                  message, client_serial);
03001 }
03002 
03003 static dbus_bool_t
03004 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03005                                           DBusMessage    *message,
03006                                           dbus_uint32_t  *client_serial)
03007 {
03008   DBusPreallocatedSend *preallocated;
03009 
03010   _dbus_assert (connection != NULL);
03011   _dbus_assert (message != NULL);
03012   
03013   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03014   if (preallocated == NULL)
03015     return FALSE;
03016 
03017   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03018                                                          preallocated,
03019                                                          message,
03020                                                          client_serial);
03021   return TRUE;
03022 }
03023 
03045 dbus_bool_t
03046 dbus_connection_send (DBusConnection *connection,
03047                       DBusMessage    *message,
03048                       dbus_uint32_t  *serial)
03049 {
03050   _dbus_return_val_if_fail (connection != NULL, FALSE);
03051   _dbus_return_val_if_fail (message != NULL, FALSE);
03052 
03053   CONNECTION_LOCK (connection);
03054 
03055   return _dbus_connection_send_and_unlock (connection,
03056                                            message,
03057                                            serial);
03058 }
03059 
03060 static dbus_bool_t
03061 reply_handler_timeout (void *data)
03062 {
03063   DBusConnection *connection;
03064   DBusDispatchStatus status;
03065   DBusPendingCall *pending = data;
03066 
03067   connection = _dbus_pending_call_get_connection_and_lock (pending);
03068 
03069   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03070                                                    connection);
03071   _dbus_connection_remove_timeout_unlocked (connection,
03072                                             _dbus_pending_call_get_timeout_unlocked (pending));
03073   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03074 
03075   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03076   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03077 
03078   /* Unlocks, and calls out to user code */
03079   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03080   
03081   return TRUE;
03082 }
03083 
03121 dbus_bool_t
03122 dbus_connection_send_with_reply (DBusConnection     *connection,
03123                                  DBusMessage        *message,
03124                                  DBusPendingCall   **pending_return,
03125                                  int                 timeout_milliseconds)
03126 {
03127   DBusPendingCall *pending;
03128   dbus_int32_t serial = -1;
03129   DBusDispatchStatus status;
03130 
03131   _dbus_return_val_if_fail (connection != NULL, FALSE);
03132   _dbus_return_val_if_fail (message != NULL, FALSE);
03133   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03134 
03135   if (pending_return)
03136     *pending_return = NULL;
03137 
03138   CONNECTION_LOCK (connection);
03139 
03140    if (!_dbus_connection_get_is_connected_unlocked (connection))
03141     {
03142       CONNECTION_UNLOCK (connection);
03143 
03144       *pending_return = NULL;
03145 
03146       return TRUE;
03147     }
03148 
03149   pending = _dbus_pending_call_new_unlocked (connection,
03150                                              timeout_milliseconds,
03151                                              reply_handler_timeout);
03152 
03153   if (pending == NULL)
03154     {
03155       CONNECTION_UNLOCK (connection);
03156       return FALSE;
03157     }
03158 
03159   /* Assign a serial to the message */
03160   serial = dbus_message_get_serial (message);
03161   if (serial == 0)
03162     {
03163       serial = _dbus_connection_get_next_client_serial (connection);
03164       _dbus_message_set_serial (message, serial);
03165     }
03166 
03167   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03168     goto error;
03169     
03170   /* Insert the serial in the pending replies hash;
03171    * hash takes a refcount on DBusPendingCall.
03172    * Also, add the timeout.
03173    */
03174   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03175                                                       pending))
03176     goto error;
03177  
03178   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03179     {
03180       _dbus_connection_detach_pending_call_and_unlock (connection,
03181                                                        pending);
03182       goto error_unlocked;
03183     }
03184 
03185   if (pending_return)
03186     *pending_return = pending; /* hand off refcount */
03187   else
03188     {
03189       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03190       /* we still have a ref to the pending call in this case, we unref
03191        * after unlocking, below
03192        */
03193     }
03194 
03195   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03196 
03197   /* this calls out to user code */
03198   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03199 
03200   if (pending_return == NULL)
03201     dbus_pending_call_unref (pending);
03202   
03203   return TRUE;
03204 
03205  error:
03206   CONNECTION_UNLOCK (connection);
03207  error_unlocked:
03208   dbus_pending_call_unref (pending);
03209   return FALSE;
03210 }
03211 
03242 DBusMessage*
03243 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03244                                            DBusMessage        *message,
03245                                            int                 timeout_milliseconds,
03246                                            DBusError          *error)
03247 {
03248   DBusMessage *reply;
03249   DBusPendingCall *pending;
03250   
03251   _dbus_return_val_if_fail (connection != NULL, NULL);
03252   _dbus_return_val_if_fail (message != NULL, NULL);
03253   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03254   _dbus_return_val_if_error_is_set (error, NULL);
03255   
03256   if (!dbus_connection_send_with_reply (connection, message,
03257                                         &pending, timeout_milliseconds))
03258     {
03259       _DBUS_SET_OOM (error);
03260       return NULL;
03261     }
03262 
03263   if (pending == NULL)
03264     {
03265       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03266       return NULL;
03267     }
03268   
03269   dbus_pending_call_block (pending);
03270 
03271   reply = dbus_pending_call_steal_reply (pending);
03272   dbus_pending_call_unref (pending);
03273 
03274   /* call_complete_and_unlock() called from pending_call_block() should
03275    * always fill this in.
03276    */
03277   _dbus_assert (reply != NULL);
03278   
03279    if (dbus_set_error_from_message (error, reply))
03280     {
03281       dbus_message_unref (reply);
03282       return NULL;
03283     }
03284   else
03285     return reply;
03286 }
03287 
03296 DBusDispatchStatus
03297 _dbus_connection_flush_unlocked (DBusConnection *connection)
03298 {
03299   /* We have to specify DBUS_ITERATION_DO_READING here because
03300    * otherwise we could have two apps deadlock if they are both doing
03301    * a flush(), and the kernel buffers fill up. This could change the
03302    * dispatch status.
03303    */
03304   DBusDispatchStatus status;
03305 
03306   HAVE_LOCK_CHECK (connection);
03307   
03308   while (connection->n_outgoing > 0 &&
03309          _dbus_connection_get_is_connected_unlocked (connection))
03310     {
03311       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03312       HAVE_LOCK_CHECK (connection);
03313       _dbus_connection_do_iteration_unlocked (connection,
03314                                               DBUS_ITERATION_DO_READING |
03315                                               DBUS_ITERATION_DO_WRITING |
03316                                               DBUS_ITERATION_BLOCK,
03317                                               -1);
03318     }
03319 
03320   HAVE_LOCK_CHECK (connection);
03321   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03322   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03323 
03324   HAVE_LOCK_CHECK (connection);
03325   return status;
03326 }
03327 
03333 void
03334 dbus_connection_flush (DBusConnection *connection)
03335 {
03336   /* We have to specify DBUS_ITERATION_DO_READING here because
03337    * otherwise we could have two apps deadlock if they are both doing
03338    * a flush(), and the kernel buffers fill up. This could change the
03339    * dispatch status.
03340    */
03341   DBusDispatchStatus status;
03342 
03343   _dbus_return_if_fail (connection != NULL);
03344   
03345   CONNECTION_LOCK (connection);
03346 
03347   status = _dbus_connection_flush_unlocked (connection);
03348   
03349   HAVE_LOCK_CHECK (connection);
03350   /* Unlocks and calls out to user code */
03351   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03352 
03353   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03354 }
03355 
03366 static dbus_bool_t
03367 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03368                                      int             timeout_milliseconds, 
03369                                      dbus_bool_t     dispatch)
03370 {
03371   DBusDispatchStatus dstatus;
03372   dbus_bool_t no_progress_possible;
03373   
03374   dstatus = dbus_connection_get_dispatch_status (connection);
03375 
03376   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03377     {
03378       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03379       dbus_connection_dispatch (connection);
03380       CONNECTION_LOCK (connection);
03381     }
03382   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03383     {
03384       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03385       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03386       CONNECTION_LOCK (connection);
03387     }
03388   else
03389     {
03390       CONNECTION_LOCK (connection);
03391       if (_dbus_connection_get_is_connected_unlocked (connection))
03392         {
03393           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03394           _dbus_connection_do_iteration_unlocked (connection,
03395                                                   DBUS_ITERATION_DO_READING |
03396                                                   DBUS_ITERATION_DO_WRITING |
03397                                                   DBUS_ITERATION_BLOCK,
03398                                                   timeout_milliseconds);
03399         }
03400     }
03401   
03402   HAVE_LOCK_CHECK (connection);
03403   /* If we can dispatch, we can make progress until the Disconnected message
03404    * has been processed; if we can only read/write, we can make progress
03405    * as long as the transport is open.
03406    */
03407   if (dispatch)
03408     no_progress_possible = connection->n_incoming == 0 &&
03409       connection->disconnect_message_link == NULL;
03410   else
03411     no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03412   CONNECTION_UNLOCK (connection);
03413   return !no_progress_possible; /* TRUE if we can make more progress */
03414 }
03415 
03416 
03451 dbus_bool_t
03452 dbus_connection_read_write_dispatch (DBusConnection *connection,
03453                                      int             timeout_milliseconds)
03454 {
03455   _dbus_return_val_if_fail (connection != NULL, FALSE);
03456   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03457    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03458 }
03459 
03483 dbus_bool_t 
03484 dbus_connection_read_write (DBusConnection *connection, 
03485                             int             timeout_milliseconds) 
03486 { 
03487   _dbus_return_val_if_fail (connection != NULL, FALSE);
03488   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03489    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03490 }
03491 
03492 /* We need to call this anytime we pop the head of the queue, and then
03493  * update_dispatch_status_and_unlock needs to be called afterward
03494  * which will "process" the disconnected message and set
03495  * disconnected_message_processed.
03496  */
03497 static void
03498 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03499                                              DBusMessage    *head_of_queue)
03500 {
03501   HAVE_LOCK_CHECK (connection);
03502 
03503   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03504   if (connection->disconnect_message_link == NULL &&
03505       dbus_message_is_signal (head_of_queue,
03506                               DBUS_INTERFACE_LOCAL,
03507                               "Disconnected"))
03508     {
03509       connection->disconnected_message_arrived = TRUE;
03510     }
03511 }
03512 
03532 DBusMessage*
03533 dbus_connection_borrow_message (DBusConnection *connection)
03534 {
03535   DBusDispatchStatus status;
03536   DBusMessage *message;
03537 
03538   _dbus_return_val_if_fail (connection != NULL, NULL);
03539 
03540   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03541   
03542   /* this is called for the side effect that it queues
03543    * up any messages from the transport
03544    */
03545   status = dbus_connection_get_dispatch_status (connection);
03546   if (status != DBUS_DISPATCH_DATA_REMAINS)
03547     return NULL;
03548   
03549   CONNECTION_LOCK (connection);
03550 
03551   _dbus_connection_acquire_dispatch (connection);
03552 
03553   /* While a message is outstanding, the dispatch lock is held */
03554   _dbus_assert (connection->message_borrowed == NULL);
03555 
03556   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03557   
03558   message = connection->message_borrowed;
03559 
03560   check_disconnected_message_arrived_unlocked (connection, message);
03561   
03562   /* Note that we KEEP the dispatch lock until the message is returned */
03563   if (message == NULL)
03564     _dbus_connection_release_dispatch (connection);
03565 
03566   CONNECTION_UNLOCK (connection);
03567 
03568   /* We don't update dispatch status until it's returned or stolen */
03569   
03570   return message;
03571 }
03572 
03581 void
03582 dbus_connection_return_message (DBusConnection *connection,
03583                                 DBusMessage    *message)
03584 {
03585   DBusDispatchStatus status;
03586   
03587   _dbus_return_if_fail (connection != NULL);
03588   _dbus_return_if_fail (message != NULL);
03589   _dbus_return_if_fail (message == connection->message_borrowed);
03590   _dbus_return_if_fail (connection->dispatch_acquired);
03591   
03592   CONNECTION_LOCK (connection);
03593   
03594   _dbus_assert (message == connection->message_borrowed);
03595   
03596   connection->message_borrowed = NULL;
03597 
03598   _dbus_connection_release_dispatch (connection); 
03599 
03600   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03601   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03602 }
03603 
03613 void
03614 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03615                                         DBusMessage    *message)
03616 {
03617   DBusMessage *pop_message;
03618   DBusDispatchStatus status;
03619 
03620   _dbus_return_if_fail (connection != NULL);
03621   _dbus_return_if_fail (message != NULL);
03622   _dbus_return_if_fail (message == connection->message_borrowed);
03623   _dbus_return_if_fail (connection->dispatch_acquired);
03624   
03625   CONNECTION_LOCK (connection);
03626  
03627   _dbus_assert (message == connection->message_borrowed);
03628 
03629   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03630   _dbus_assert (message == pop_message);
03631   
03632   connection->n_incoming -= 1;
03633  
03634   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03635                  message, connection->n_incoming);
03636  
03637   connection->message_borrowed = NULL;
03638 
03639   _dbus_connection_release_dispatch (connection);
03640 
03641   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03642   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03643 }
03644 
03645 /* See dbus_connection_pop_message, but requires the caller to own
03646  * the lock before calling. May drop the lock while running.
03647  */
03648 static DBusList*
03649 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03650 {
03651   HAVE_LOCK_CHECK (connection);
03652   
03653   _dbus_assert (connection->message_borrowed == NULL);
03654   
03655   if (connection->n_incoming > 0)
03656     {
03657       DBusList *link;
03658 
03659       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03660       connection->n_incoming -= 1;
03661 
03662       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03663                      link->data,
03664                      dbus_message_get_type (link->data),
03665                      dbus_message_get_path (link->data) ?
03666                      dbus_message_get_path (link->data) :
03667                      "no path",
03668                      dbus_message_get_interface (link->data) ?
03669                      dbus_message_get_interface (link->data) :
03670                      "no interface",
03671                      dbus_message_get_member (link->data) ?
03672                      dbus_message_get_member (link->data) :
03673                      "no member",
03674                      dbus_message_get_signature (link->data),
03675                      connection, connection->n_incoming);
03676 
03677       check_disconnected_message_arrived_unlocked (connection, link->data);
03678       
03679       return link;
03680     }
03681   else
03682     return NULL;
03683 }
03684 
03685 /* See dbus_connection_pop_message, but requires the caller to own
03686  * the lock before calling. May drop the lock while running.
03687  */
03688 static DBusMessage*
03689 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03690 {
03691   DBusList *link;
03692 
03693   HAVE_LOCK_CHECK (connection);
03694   
03695   link = _dbus_connection_pop_message_link_unlocked (connection);
03696 
03697   if (link != NULL)
03698     {
03699       DBusMessage *message;
03700       
03701       message = link->data;
03702       
03703       _dbus_list_free_link (link);
03704       
03705       return message;
03706     }
03707   else
03708     return NULL;
03709 }
03710 
03711 static void
03712 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03713                                                 DBusList       *message_link)
03714 {
03715   HAVE_LOCK_CHECK (connection);
03716   
03717   _dbus_assert (message_link != NULL);
03718   /* You can't borrow a message while a link is outstanding */
03719   _dbus_assert (connection->message_borrowed == NULL);
03720   /* We had to have the dispatch lock across the pop/putback */
03721   _dbus_assert (connection->dispatch_acquired);
03722 
03723   _dbus_list_prepend_link (&connection->incoming_messages,
03724                            message_link);
03725   connection->n_incoming += 1;
03726 
03727   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03728                  message_link->data,
03729                  dbus_message_get_type (message_link->data),
03730                  dbus_message_get_interface (message_link->data) ?
03731                  dbus_message_get_interface (message_link->data) :
03732                  "no interface",
03733                  dbus_message_get_member (message_link->data) ?
03734                  dbus_message_get_member (message_link->data) :
03735                  "no member",
03736                  dbus_message_get_signature (message_link->data),
03737                  connection, connection->n_incoming);
03738 }
03739 
03759 DBusMessage*
03760 dbus_connection_pop_message (DBusConnection *connection)
03761 {
03762   DBusMessage *message;
03763   DBusDispatchStatus status;
03764 
03765   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03766   
03767   /* this is called for the side effect that it queues
03768    * up any messages from the transport
03769    */
03770   status = dbus_connection_get_dispatch_status (connection);
03771   if (status != DBUS_DISPATCH_DATA_REMAINS)
03772     return NULL;
03773   
03774   CONNECTION_LOCK (connection);
03775   _dbus_connection_acquire_dispatch (connection);
03776   HAVE_LOCK_CHECK (connection);
03777   
03778   message = _dbus_connection_pop_message_unlocked (connection);
03779 
03780   _dbus_verbose ("Returning popped message %p\n", message);    
03781 
03782   _dbus_connection_release_dispatch (connection);
03783 
03784   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03785   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03786   
03787   return message;
03788 }
03789 
03797 static void
03798 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03799 {
03800   HAVE_LOCK_CHECK (connection);
03801 
03802   _dbus_connection_ref_unlocked (connection);
03803   CONNECTION_UNLOCK (connection);
03804   
03805   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03806   _dbus_mutex_lock (connection->dispatch_mutex);
03807 
03808   while (connection->dispatch_acquired)
03809     {
03810       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03811       _dbus_condvar_wait (connection->dispatch_cond, 
03812                           connection->dispatch_mutex);
03813     }
03814   
03815   _dbus_assert (!connection->dispatch_acquired);
03816 
03817   connection->dispatch_acquired = TRUE;
03818 
03819   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03820   _dbus_mutex_unlock (connection->dispatch_mutex);
03821   
03822   CONNECTION_LOCK (connection);
03823   _dbus_connection_unref_unlocked (connection);
03824 }
03825 
03833 static void
03834 _dbus_connection_release_dispatch (DBusConnection *connection)
03835 {
03836   HAVE_LOCK_CHECK (connection);
03837   
03838   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03839   _dbus_mutex_lock (connection->dispatch_mutex);
03840   
03841   _dbus_assert (connection->dispatch_acquired);
03842 
03843   connection->dispatch_acquired = FALSE;
03844   _dbus_condvar_wake_one (connection->dispatch_cond);
03845 
03846   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03847   _dbus_mutex_unlock (connection->dispatch_mutex);
03848 }
03849 
03850 static void
03851 _dbus_connection_failed_pop (DBusConnection *connection,
03852                              DBusList       *message_link)
03853 {
03854   _dbus_list_prepend_link (&connection->incoming_messages,
03855                            message_link);
03856   connection->n_incoming += 1;
03857 }
03858 
03859 /* Note this may be called multiple times since we don't track whether we already did it */
03860 static void
03861 notify_disconnected_unlocked (DBusConnection *connection)
03862 {
03863   HAVE_LOCK_CHECK (connection);
03864 
03865   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
03866    * connection from dbus_bus_get(). We make the same guarantee for
03867    * dbus_connection_open() but in a different way since we don't want to
03868    * unref right here; we instead check for connectedness before returning
03869    * the connection from the hash.
03870    */
03871   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03872 
03873   /* Dump the outgoing queue, we aren't going to be able to
03874    * send it now, and we'd like accessors like
03875    * dbus_connection_get_outgoing_size() to be accurate.
03876    */
03877   if (connection->n_outgoing > 0)
03878     {
03879       DBusList *link;
03880       
03881       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03882                      connection->n_outgoing);
03883       
03884       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03885         {
03886           _dbus_connection_message_sent (connection, link->data);
03887         }
03888     } 
03889 }
03890 
03891 /* Note this may be called multiple times since we don't track whether we already did it */
03892 static DBusDispatchStatus
03893 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03894 {
03895   HAVE_LOCK_CHECK (connection);
03896   
03897   if (connection->disconnect_message_link != NULL)
03898     {
03899       _dbus_verbose ("Sending disconnect message from %s\n",
03900                      _DBUS_FUNCTION_NAME);
03901       
03902       /* If we have pending calls, queue their timeouts - we want the Disconnected
03903        * to be the last message, after these timeouts.
03904        */
03905       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03906       
03907       /* We haven't sent the disconnect message already,
03908        * and all real messages have been queued up.
03909        */
03910       _dbus_connection_queue_synthesized_message_link (connection,
03911                                                        connection->disconnect_message_link);
03912       connection->disconnect_message_link = NULL;
03913 
03914       return DBUS_DISPATCH_DATA_REMAINS;
03915     }
03916 
03917   return DBUS_DISPATCH_COMPLETE;
03918 }
03919 
03920 static DBusDispatchStatus
03921 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03922 {
03923   HAVE_LOCK_CHECK (connection);
03924   
03925   if (connection->n_incoming > 0)
03926     return DBUS_DISPATCH_DATA_REMAINS;
03927   else if (!_dbus_transport_queue_messages (connection->transport))
03928     return DBUS_DISPATCH_NEED_MEMORY;
03929   else
03930     {
03931       DBusDispatchStatus status;
03932       dbus_bool_t is_connected;
03933       
03934       status = _dbus_transport_get_dispatch_status (connection->transport);
03935       is_connected = _dbus_transport_get_is_connected (connection->transport);
03936 
03937       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03938                      DISPATCH_STATUS_NAME (status), is_connected);
03939       
03940       if (!is_connected)
03941         {
03942           /* It's possible this would be better done by having an explicit
03943            * notification from _dbus_transport_disconnect() that would
03944            * synchronously do this, instead of waiting for the next dispatch
03945            * status check. However, probably not good to change until it causes
03946            * a problem.
03947            */
03948           notify_disconnected_unlocked (connection);
03949 
03950           /* I'm not sure this is needed; the idea is that we want to
03951            * queue the Disconnected only after we've read all the
03952            * messages, but if we're disconnected maybe we are guaranteed
03953            * to have read them all ?
03954            */
03955           if (status == DBUS_DISPATCH_COMPLETE)
03956             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03957         }
03958       
03959       if (status != DBUS_DISPATCH_COMPLETE)
03960         return status;
03961       else if (connection->n_incoming > 0)
03962         return DBUS_DISPATCH_DATA_REMAINS;
03963       else
03964         return DBUS_DISPATCH_COMPLETE;
03965     }
03966 }
03967 
03968 static void
03969 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03970                                                     DBusDispatchStatus new_status)
03971 {
03972   dbus_bool_t changed;
03973   DBusDispatchStatusFunction function;
03974   void *data;
03975 
03976   HAVE_LOCK_CHECK (connection);
03977 
03978   _dbus_connection_ref_unlocked (connection);
03979 
03980   changed = new_status != connection->last_dispatch_status;
03981 
03982   connection->last_dispatch_status = new_status;
03983 
03984   function = connection->dispatch_status_function;
03985   data = connection->dispatch_status_data;
03986 
03987   if (connection->disconnected_message_arrived &&
03988       !connection->disconnected_message_processed)
03989     {
03990       connection->disconnected_message_processed = TRUE;
03991       
03992       /* this does an unref, but we have a ref
03993        * so we should not run the finalizer here
03994        * inside the lock.
03995        */
03996       connection_forget_shared_unlocked (connection);
03997 
03998       if (connection->exit_on_disconnect)
03999         {
04000           CONNECTION_UNLOCK (connection);            
04001           
04002           _dbus_verbose ("Exiting on Disconnected signal\n");
04003           _dbus_exit (1);
04004           _dbus_assert_not_reached ("Call to exit() returned");
04005         }
04006     }
04007   
04008   /* We drop the lock */
04009   CONNECTION_UNLOCK (connection);
04010   
04011   if (changed && function)
04012     {
04013       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04014                      connection, new_status,
04015                      DISPATCH_STATUS_NAME (new_status));
04016       (* function) (connection, new_status, data);      
04017     }
04018   
04019   dbus_connection_unref (connection);
04020 }
04021 
04047 DBusDispatchStatus
04048 dbus_connection_get_dispatch_status (DBusConnection *connection)
04049 {
04050   DBusDispatchStatus status;
04051 
04052   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04053 
04054   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04055   
04056   CONNECTION_LOCK (connection);
04057 
04058   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04059   
04060   CONNECTION_UNLOCK (connection);
04061 
04062   return status;
04063 }
04064 
04068 static DBusHandlerResult
04069 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04070                                                  DBusMessage    *message)
04071 {
04072   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04073     {
04074       /* This means we're letting the bus route this message */
04075       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04076     }
04077   else if (dbus_message_is_method_call (message,
04078                                         DBUS_INTERFACE_PEER,
04079                                         "Ping"))
04080     {
04081       DBusMessage *ret;
04082       dbus_bool_t sent;
04083       
04084       ret = dbus_message_new_method_return (message);
04085       if (ret == NULL)
04086         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04087      
04088       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04089 
04090       dbus_message_unref (ret);
04091 
04092       if (!sent)
04093         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04094       
04095       return DBUS_HANDLER_RESULT_HANDLED;
04096     }
04097   else if (dbus_message_is_method_call (message,
04098                                         DBUS_INTERFACE_PEER,
04099                                         "GetMachineId"))
04100     {
04101       DBusMessage *ret;
04102       dbus_bool_t sent;
04103       DBusString uuid;
04104       
04105       ret = dbus_message_new_method_return (message);
04106       if (ret == NULL)
04107         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04108 
04109       sent = FALSE;
04110       _dbus_string_init (&uuid);
04111       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04112         {
04113           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04114           if (dbus_message_append_args (ret,
04115                                         DBUS_TYPE_STRING, &v_STRING,
04116                                         DBUS_TYPE_INVALID))
04117             {
04118               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04119             }
04120         }
04121       _dbus_string_free (&uuid);
04122       
04123       dbus_message_unref (ret);
04124 
04125       if (!sent)
04126         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04127       
04128       return DBUS_HANDLER_RESULT_HANDLED;
04129     }
04130   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04131     {
04132       /* We need to bounce anything else with this interface, otherwise apps
04133        * could start extending the interface and when we added extensions
04134        * here to DBusConnection we'd break those apps.
04135        */
04136       
04137       DBusMessage *ret;
04138       dbus_bool_t sent;
04139       
04140       ret = dbus_message_new_error (message,
04141                                     DBUS_ERROR_UNKNOWN_METHOD,
04142                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04143       if (ret == NULL)
04144         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04145       
04146       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04147       
04148       dbus_message_unref (ret);
04149       
04150       if (!sent)
04151         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04152       
04153       return DBUS_HANDLER_RESULT_HANDLED;
04154     }
04155   else
04156     {
04157       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04158     }
04159 }
04160 
04167 static DBusHandlerResult
04168 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04169                                                            DBusMessage    *message)
04170 {
04171   /* We just run one filter for now but have the option to run more
04172      if the spec calls for it in the future */
04173 
04174   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04175 }
04176 
04219 DBusDispatchStatus
04220 dbus_connection_dispatch (DBusConnection *connection)
04221 {
04222   DBusMessage *message;
04223   DBusList *link, *filter_list_copy, *message_link;
04224   DBusHandlerResult result;
04225   DBusPendingCall *pending;
04226   dbus_int32_t reply_serial;
04227   DBusDispatchStatus status;
04228 
04229   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04230 
04231   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04232   
04233   CONNECTION_LOCK (connection);
04234   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04235   if (status != DBUS_DISPATCH_DATA_REMAINS)
04236     {
04237       /* unlocks and calls out to user code */
04238       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04239       return status;
04240     }
04241   
04242   /* We need to ref the connection since the callback could potentially
04243    * drop the last ref to it
04244    */
04245   _dbus_connection_ref_unlocked (connection);
04246 
04247   _dbus_connection_acquire_dispatch (connection);
04248   HAVE_LOCK_CHECK (connection);
04249 
04250   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04251   if (message_link == NULL)
04252     {
04253       /* another thread dispatched our stuff */
04254 
04255       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04256       
04257       _dbus_connection_release_dispatch (connection);
04258 
04259       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04260 
04261       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04262       
04263       dbus_connection_unref (connection);
04264       
04265       return status;
04266     }
04267 
04268   message = message_link->data;
04269 
04270   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04271                  message,
04272                  dbus_message_get_type (message),
04273                  dbus_message_get_interface (message) ?
04274                  dbus_message_get_interface (message) :
04275                  "no interface",
04276                  dbus_message_get_member (message) ?
04277                  dbus_message_get_member (message) :
04278                  "no member",
04279                  dbus_message_get_signature (message));
04280 
04281   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04282   
04283   /* Pending call handling must be first, because if you do
04284    * dbus_connection_send_with_reply_and_block() or
04285    * dbus_pending_call_block() then no handlers/filters will be run on
04286    * the reply. We want consistent semantics in the case where we
04287    * dbus_connection_dispatch() the reply.
04288    */
04289   
04290   reply_serial = dbus_message_get_reply_serial (message);
04291   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04292                                          reply_serial);
04293   if (pending)
04294     {
04295       _dbus_verbose ("Dispatching a pending reply\n");
04296       complete_pending_call_and_unlock (connection, pending, message);
04297       pending = NULL; /* it's probably unref'd */
04298       
04299       CONNECTION_LOCK (connection);
04300       _dbus_verbose ("pending call completed in dispatch\n");
04301       result = DBUS_HANDLER_RESULT_HANDLED;
04302       goto out;
04303     }
04304 
04305   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04306   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04307     goto out;
04308  
04309   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04310     {
04311       _dbus_connection_release_dispatch (connection);
04312       HAVE_LOCK_CHECK (connection);
04313       
04314       _dbus_connection_failed_pop (connection, message_link);
04315 
04316       /* unlocks and calls user code */
04317       _dbus_connection_update_dispatch_status_and_unlock (connection,
04318                                                           DBUS_DISPATCH_NEED_MEMORY);
04319 
04320       if (pending)
04321         dbus_pending_call_unref (pending);
04322       dbus_connection_unref (connection);
04323       
04324       return DBUS_DISPATCH_NEED_MEMORY;
04325     }
04326   
04327   _dbus_list_foreach (&filter_list_copy,
04328                       (DBusForeachFunction)_dbus_message_filter_ref,
04329                       NULL);
04330 
04331   /* We're still protected from dispatch() reentrancy here
04332    * since we acquired the dispatcher
04333    */
04334   CONNECTION_UNLOCK (connection);
04335   
04336   link = _dbus_list_get_first_link (&filter_list_copy);
04337   while (link != NULL)
04338     {
04339       DBusMessageFilter *filter = link->data;
04340       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04341 
04342       if (filter->function == NULL)
04343         {
04344           _dbus_verbose ("  filter was removed in a callback function\n");
04345           link = next;
04346           continue;
04347         }
04348 
04349       _dbus_verbose ("  running filter on message %p\n", message);
04350       result = (* filter->function) (connection, message, filter->user_data);
04351 
04352       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04353         break;
04354 
04355       link = next;
04356     }
04357 
04358   _dbus_list_foreach (&filter_list_copy,
04359                       (DBusForeachFunction)_dbus_message_filter_unref,
04360                       NULL);
04361   _dbus_list_clear (&filter_list_copy);
04362   
04363   CONNECTION_LOCK (connection);
04364 
04365   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04366     {
04367       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04368       goto out;
04369     }
04370   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04371     {
04372       _dbus_verbose ("filter handled message in dispatch\n");
04373       goto out;
04374     }
04375 
04376   /* We're still protected from dispatch() reentrancy here
04377    * since we acquired the dispatcher
04378    */
04379   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
04380                  message,
04381                  dbus_message_get_type (message),
04382                  dbus_message_get_interface (message) ?
04383                  dbus_message_get_interface (message) :
04384                  "no interface",
04385                  dbus_message_get_member (message) ?
04386                  dbus_message_get_member (message) :
04387                  "no member",
04388                  dbus_message_get_signature (message));
04389 
04390   HAVE_LOCK_CHECK (connection);
04391   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04392                                                   message);
04393   
04394   CONNECTION_LOCK (connection);
04395 
04396   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04397     {
04398       _dbus_verbose ("object tree handled message in dispatch\n");
04399       goto out;
04400     }
04401 
04402   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04403     {
04404       DBusMessage *reply;
04405       DBusString str;
04406       DBusPreallocatedSend *preallocated;
04407 
04408       _dbus_verbose ("  sending error %s\n",
04409                      DBUS_ERROR_UNKNOWN_METHOD);
04410       
04411       if (!_dbus_string_init (&str))
04412         {
04413           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04414           _dbus_verbose ("no memory for error string in dispatch\n");
04415           goto out;
04416         }
04417               
04418       if (!_dbus_string_append_printf (&str,
04419                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04420                                        dbus_message_get_member (message),
04421                                        dbus_message_get_signature (message),
04422                                        dbus_message_get_interface (message)))
04423         {
04424           _dbus_string_free (&str);
04425           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04426           _dbus_verbose ("no memory for error string in dispatch\n");
04427           goto out;
04428         }
04429       
04430       reply = dbus_message_new_error (message,
04431                                       DBUS_ERROR_UNKNOWN_METHOD,
04432                                       _dbus_string_get_const_data (&str));
04433       _dbus_string_free (&str);
04434 
04435       if (reply == NULL)
04436         {
04437           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04438           _dbus_verbose ("no memory for error reply in dispatch\n");
04439           goto out;
04440         }
04441       
04442       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04443 
04444       if (preallocated == NULL)
04445         {
04446           dbus_message_unref (reply);
04447           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04448           _dbus_verbose ("no memory for error send in dispatch\n");
04449           goto out;
04450         }
04451 
04452       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04453                                                              reply, NULL);
04454 
04455       dbus_message_unref (reply);
04456       
04457       result = DBUS_HANDLER_RESULT_HANDLED;
04458     }
04459   
04460   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04461                  dbus_message_get_type (message),
04462                  dbus_message_get_interface (message) ?
04463                  dbus_message_get_interface (message) :
04464                  "no interface",
04465                  dbus_message_get_member (message) ?
04466                  dbus_message_get_member (message) :
04467                  "no member",
04468                  dbus_message_get_signature (message),
04469                  connection);
04470   
04471  out:
04472   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04473     {
04474       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04475       
04476       /* Put message back, and we'll start over.
04477        * Yes this means handlers must be idempotent if they
04478        * don't return HANDLED; c'est la vie.
04479        */
04480       _dbus_connection_putback_message_link_unlocked (connection,
04481                                                       message_link);
04482     }
04483   else
04484     {
04485       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04486       
04487       _dbus_list_free_link (message_link);
04488       dbus_message_unref (message); /* don't want the message to count in max message limits
04489                                      * in computing dispatch status below
04490                                      */
04491     }
04492   
04493   _dbus_connection_release_dispatch (connection);
04494   HAVE_LOCK_CHECK (connection);
04495 
04496   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04497   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04498 
04499   /* unlocks and calls user code */
04500   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04501   
04502   dbus_connection_unref (connection);
04503   
04504   return status;
04505 }
04506 
04566 dbus_bool_t
04567 dbus_connection_set_watch_functions (DBusConnection              *connection,
04568                                      DBusAddWatchFunction         add_function,
04569                                      DBusRemoveWatchFunction      remove_function,
04570                                      DBusWatchToggledFunction     toggled_function,
04571                                      void                        *data,
04572                                      DBusFreeFunction             free_data_function)
04573 {
04574   dbus_bool_t retval;
04575   DBusWatchList *watches;
04576 
04577   _dbus_return_val_if_fail (connection != NULL, FALSE);
04578   
04579   CONNECTION_LOCK (connection);
04580 
04581 #ifndef DBUS_DISABLE_CHECKS
04582   if (connection->watches == NULL)
04583     {
04584       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04585                                _DBUS_FUNCTION_NAME);
04586       return FALSE;
04587     }
04588 #endif
04589   
04590   /* ref connection for slightly better reentrancy */
04591   _dbus_connection_ref_unlocked (connection);
04592 
04593   /* This can call back into user code, and we need to drop the
04594    * connection lock when it does. This is kind of a lame
04595    * way to do it.
04596    */
04597   watches = connection->watches;
04598   connection->watches = NULL;
04599   CONNECTION_UNLOCK (connection);
04600 
04601   retval = _dbus_watch_list_set_functions (watches,
04602                                            add_function, remove_function,
04603                                            toggled_function,
04604                                            data, free_data_function);
04605   CONNECTION_LOCK (connection);
04606   connection->watches = watches;
04607   
04608   CONNECTION_UNLOCK (connection);
04609   /* drop our paranoid refcount */
04610   dbus_connection_unref (connection);
04611   
04612   return retval;
04613 }
04614 
04648 dbus_bool_t
04649 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04650                                          DBusAddTimeoutFunction     add_function,
04651                                          DBusRemoveTimeoutFunction  remove_function,
04652                                          DBusTimeoutToggledFunction toggled_function,
04653                                          void                      *data,
04654                                          DBusFreeFunction           free_data_function)
04655 {
04656   dbus_bool_t retval;
04657   DBusTimeoutList *timeouts;
04658 
04659   _dbus_return_val_if_fail (connection != NULL, FALSE);
04660   
04661   CONNECTION_LOCK (connection);
04662 
04663 #ifndef DBUS_DISABLE_CHECKS
04664   if (connection->timeouts == NULL)
04665     {
04666       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04667                                _DBUS_FUNCTION_NAME);
04668       return FALSE;
04669     }
04670 #endif
04671   
04672   /* ref connection for slightly better reentrancy */
04673   _dbus_connection_ref_unlocked (connection);
04674 
04675   timeouts = connection->timeouts;
04676   connection->timeouts = NULL;
04677   CONNECTION_UNLOCK (connection);
04678   
04679   retval = _dbus_timeout_list_set_functions (timeouts,
04680                                              add_function, remove_function,
04681                                              toggled_function,
04682                                              data, free_data_function);
04683   CONNECTION_LOCK (connection);
04684   connection->timeouts = timeouts;
04685   
04686   CONNECTION_UNLOCK (connection);
04687   /* drop our paranoid refcount */
04688   dbus_connection_unref (connection);
04689 
04690   return retval;
04691 }
04692 
04707 void
04708 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04709                                           DBusWakeupMainFunction     wakeup_main_function,
04710                                           void                      *data,
04711                                           DBusFreeFunction           free_data_function)
04712 {
04713   void *old_data;
04714   DBusFreeFunction old_free_data;
04715 
04716   _dbus_return_if_fail (connection != NULL);
04717   
04718   CONNECTION_LOCK (connection);
04719   old_data = connection->wakeup_main_data;
04720   old_free_data = connection->free_wakeup_main_data;
04721 
04722   connection->wakeup_main_function = wakeup_main_function;
04723   connection->wakeup_main_data = data;
04724   connection->free_wakeup_main_data = free_data_function;
04725   
04726   CONNECTION_UNLOCK (connection);
04727 
04728   /* Callback outside the lock */
04729   if (old_free_data)
04730     (*old_free_data) (old_data);
04731 }
04732 
04753 void
04754 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04755                                               DBusDispatchStatusFunction  function,
04756                                               void                       *data,
04757                                               DBusFreeFunction            free_data_function)
04758 {
04759   void *old_data;
04760   DBusFreeFunction old_free_data;
04761 
04762   _dbus_return_if_fail (connection != NULL);
04763   
04764   CONNECTION_LOCK (connection);
04765   old_data = connection->dispatch_status_data;
04766   old_free_data = connection->free_dispatch_status_data;
04767 
04768   connection->dispatch_status_function = function;
04769   connection->dispatch_status_data = data;
04770   connection->free_dispatch_status_data = free_data_function;
04771   
04772   CONNECTION_UNLOCK (connection);
04773 
04774   /* Callback outside the lock */
04775   if (old_free_data)
04776     (*old_free_data) (old_data);
04777 }
04778 
04798 dbus_bool_t
04799 dbus_connection_get_unix_fd (DBusConnection *connection,
04800                              int            *fd)
04801 {
04802   _dbus_return_val_if_fail (connection != NULL, FALSE);
04803   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04804 
04805 #ifdef DBUS_WIN
04806   /* FIXME do this on a lower level */
04807   return FALSE;
04808 #endif
04809   
04810   return dbus_connection_get_socket(connection, fd);
04811 }
04812 
04828 dbus_bool_t
04829 dbus_connection_get_socket(DBusConnection              *connection,
04830                            int                         *fd)
04831 {
04832   dbus_bool_t retval;
04833 
04834   _dbus_return_val_if_fail (connection != NULL, FALSE);
04835   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04836   
04837   CONNECTION_LOCK (connection);
04838   
04839   retval = _dbus_transport_get_socket_fd (connection->transport,
04840                                           fd);
04841 
04842   CONNECTION_UNLOCK (connection);
04843 
04844   return retval;
04845 }
04846 
04847 
04870 dbus_bool_t
04871 dbus_connection_get_unix_user (DBusConnection *connection,
04872                                unsigned long  *uid)
04873 {
04874   dbus_bool_t result;
04875 
04876   _dbus_return_val_if_fail (connection != NULL, FALSE);
04877   _dbus_return_val_if_fail (uid != NULL, FALSE);
04878   
04879   CONNECTION_LOCK (connection);
04880 
04881   if (!_dbus_transport_get_is_authenticated (connection->transport))
04882     result = FALSE;
04883   else
04884     result = _dbus_transport_get_unix_user (connection->transport,
04885                                             uid);
04886 
04887 #ifdef DBUS_WIN
04888   _dbus_assert (!result);
04889 #endif
04890   
04891   CONNECTION_UNLOCK (connection);
04892 
04893   return result;
04894 }
04895 
04906 dbus_bool_t
04907 dbus_connection_get_unix_process_id (DBusConnection *connection,
04908                                      unsigned long  *pid)
04909 {
04910   dbus_bool_t result;
04911 
04912   _dbus_return_val_if_fail (connection != NULL, FALSE);
04913   _dbus_return_val_if_fail (pid != NULL, FALSE);
04914   
04915   CONNECTION_LOCK (connection);
04916 
04917   if (!_dbus_transport_get_is_authenticated (connection->transport))
04918     result = FALSE;
04919   else
04920     result = _dbus_transport_get_unix_process_id (connection->transport,
04921                                                   pid);
04922 #ifdef DBUS_WIN
04923   _dbus_assert (!result);
04924 #endif
04925   
04926   CONNECTION_UNLOCK (connection);
04927 
04928   return result;
04929 }
04930 
04953 void
04954 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04955                                         DBusAllowUnixUserFunction   function,
04956                                         void                       *data,
04957                                         DBusFreeFunction            free_data_function)
04958 {
04959   void *old_data = NULL;
04960   DBusFreeFunction old_free_function = NULL;
04961 
04962   _dbus_return_if_fail (connection != NULL);
04963   
04964   CONNECTION_LOCK (connection);
04965   _dbus_transport_set_unix_user_function (connection->transport,
04966                                           function, data, free_data_function,
04967                                           &old_data, &old_free_function);
04968   CONNECTION_UNLOCK (connection);
04969 
04970   if (old_free_function != NULL)
04971     (* old_free_function) (old_data);
04972 }
04973 
05005 dbus_bool_t
05006 dbus_connection_get_windows_user (DBusConnection             *connection,
05007                                   char                      **windows_sid_p)
05008 {
05009   dbus_bool_t result;
05010 
05011   _dbus_return_val_if_fail (connection != NULL, FALSE);
05012   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05013   
05014   CONNECTION_LOCK (connection);
05015 
05016   if (!_dbus_transport_get_is_authenticated (connection->transport))
05017     result = FALSE;
05018   else
05019     result = _dbus_transport_get_windows_user (connection->transport,
05020                                                windows_sid_p);
05021 
05022 #ifdef DBUS_UNIX
05023   _dbus_assert (!result);
05024 #endif
05025   
05026   CONNECTION_UNLOCK (connection);
05027 
05028   return result;
05029 }
05030 
05052 void
05053 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05054                                            DBusAllowWindowsUserFunction function,
05055                                            void                        *data,
05056                                            DBusFreeFunction             free_data_function)
05057 {
05058   void *old_data = NULL;
05059   DBusFreeFunction old_free_function = NULL;
05060 
05061   _dbus_return_if_fail (connection != NULL);
05062   
05063   CONNECTION_LOCK (connection);
05064   _dbus_transport_set_windows_user_function (connection->transport,
05065                                              function, data, free_data_function,
05066                                              &old_data, &old_free_function);
05067   CONNECTION_UNLOCK (connection);
05068 
05069   if (old_free_function != NULL)
05070     (* old_free_function) (old_data);
05071 }
05072 
05099 void
05100 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05101                                      dbus_bool_t                 value)
05102 {
05103   _dbus_return_if_fail (connection != NULL);
05104   
05105   CONNECTION_LOCK (connection);
05106   _dbus_transport_set_allow_anonymous (connection->transport, value);
05107   CONNECTION_UNLOCK (connection);
05108 }
05109 
05127 void
05128 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05129                                          dbus_bool_t                 value)
05130 {
05131   _dbus_return_if_fail (connection != NULL);
05132   
05133   CONNECTION_LOCK (connection);
05134   connection->route_peer_messages = TRUE;
05135   CONNECTION_UNLOCK (connection);
05136 }
05137 
05159 dbus_bool_t
05160 dbus_connection_add_filter (DBusConnection            *connection,
05161                             DBusHandleMessageFunction  function,
05162                             void                      *user_data,
05163                             DBusFreeFunction           free_data_function)
05164 {
05165   DBusMessageFilter *filter;
05166   
05167   _dbus_return_val_if_fail (connection != NULL, FALSE);
05168   _dbus_return_val_if_fail (function != NULL, FALSE);
05169 
05170   filter = dbus_new0 (DBusMessageFilter, 1);
05171   if (filter == NULL)
05172     return FALSE;
05173 
05174   filter->refcount.value = 1;
05175   
05176   CONNECTION_LOCK (connection);
05177 
05178   if (!_dbus_list_append (&connection->filter_list,
05179                           filter))
05180     {
05181       _dbus_message_filter_unref (filter);
05182       CONNECTION_UNLOCK (connection);
05183       return FALSE;
05184     }
05185 
05186   /* Fill in filter after all memory allocated,
05187    * so we don't run the free_user_data_function
05188    * if the add_filter() fails
05189    */
05190   
05191   filter->function = function;
05192   filter->user_data = user_data;
05193   filter->free_user_data_function = free_data_function;
05194         
05195   CONNECTION_UNLOCK (connection);
05196   return TRUE;
05197 }
05198 
05211 void
05212 dbus_connection_remove_filter (DBusConnection            *connection,
05213                                DBusHandleMessageFunction  function,
05214                                void                      *user_data)
05215 {
05216   DBusList *link;
05217   DBusMessageFilter *filter;
05218   
05219   _dbus_return_if_fail (connection != NULL);
05220   _dbus_return_if_fail (function != NULL);
05221   
05222   CONNECTION_LOCK (connection);
05223 
05224   filter = NULL;
05225   
05226   link = _dbus_list_get_last_link (&connection->filter_list);
05227   while (link != NULL)
05228     {
05229       filter = link->data;
05230 
05231       if (filter->function == function &&
05232           filter->user_data == user_data)
05233         {
05234           _dbus_list_remove_link (&connection->filter_list, link);
05235           filter->function = NULL;
05236           
05237           break;
05238         }
05239         
05240       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05241     }
05242   
05243   CONNECTION_UNLOCK (connection);
05244 
05245 #ifndef DBUS_DISABLE_CHECKS
05246   if (filter == NULL)
05247     {
05248       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05249                                function, user_data);
05250       return;
05251     }
05252 #endif
05253   
05254   /* Call application code */
05255   if (filter->free_user_data_function)
05256     (* filter->free_user_data_function) (filter->user_data);
05257 
05258   filter->free_user_data_function = NULL;
05259   filter->user_data = NULL;
05260   
05261   _dbus_message_filter_unref (filter);
05262 }
05263 
05275 dbus_bool_t
05276 dbus_connection_register_object_path (DBusConnection              *connection,
05277                                       const char                  *path,
05278                                       const DBusObjectPathVTable  *vtable,
05279                                       void                        *user_data)
05280 {
05281   char **decomposed_path;
05282   dbus_bool_t retval;
05283   
05284   _dbus_return_val_if_fail (connection != NULL, FALSE);
05285   _dbus_return_val_if_fail (path != NULL, FALSE);
05286   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05287   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05288 
05289   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05290     return FALSE;
05291 
05292   CONNECTION_LOCK (connection);
05293 
05294   retval = _dbus_object_tree_register (connection->objects,
05295                                        FALSE,
05296                                        (const char **) decomposed_path, vtable,
05297                                        user_data);
05298 
05299   CONNECTION_UNLOCK (connection);
05300 
05301   dbus_free_string_array (decomposed_path);
05302 
05303   return retval;
05304 }
05305 
05318 dbus_bool_t
05319 dbus_connection_register_fallback (DBusConnection              *connection,
05320                                    const char                  *path,
05321                                    const DBusObjectPathVTable  *vtable,
05322                                    void                        *user_data)
05323 {
05324   char **decomposed_path;
05325   dbus_bool_t retval;
05326   
05327   _dbus_return_val_if_fail (connection != NULL, FALSE);
05328   _dbus_return_val_if_fail (path != NULL, FALSE);
05329   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05330   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05331 
05332   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05333     return FALSE;
05334 
05335   CONNECTION_LOCK (connection);
05336 
05337   retval = _dbus_object_tree_register (connection->objects,
05338                                        TRUE,
05339                                        (const char **) decomposed_path, vtable,
05340                                        user_data);
05341 
05342   CONNECTION_UNLOCK (connection);
05343 
05344   dbus_free_string_array (decomposed_path);
05345 
05346   return retval;
05347 }
05348 
05358 dbus_bool_t
05359 dbus_connection_unregister_object_path (DBusConnection              *connection,
05360                                         const char                  *path)
05361 {
05362   char **decomposed_path;
05363 
05364   _dbus_return_val_if_fail (connection != NULL, FALSE);
05365   _dbus_return_val_if_fail (path != NULL, FALSE);
05366   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05367 
05368   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05369       return FALSE;
05370 
05371   CONNECTION_LOCK (connection);
05372 
05373   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05374 
05375   dbus_free_string_array (decomposed_path);
05376 
05377   return TRUE;
05378 }
05379 
05390 dbus_bool_t
05391 dbus_connection_get_object_path_data (DBusConnection *connection,
05392                                       const char     *path,
05393                                       void          **data_p)
05394 {
05395   char **decomposed_path;
05396 
05397   _dbus_return_val_if_fail (connection != NULL, FALSE);
05398   _dbus_return_val_if_fail (path != NULL, FALSE);
05399   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05400 
05401   *data_p = NULL;
05402   
05403   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05404     return FALSE;
05405   
05406   CONNECTION_LOCK (connection);
05407 
05408   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05409 
05410   CONNECTION_UNLOCK (connection);
05411 
05412   dbus_free_string_array (decomposed_path);
05413 
05414   return TRUE;
05415 }
05416 
05427 dbus_bool_t
05428 dbus_connection_list_registered (DBusConnection              *connection,
05429                                  const char                  *parent_path,
05430                                  char                      ***child_entries)
05431 {
05432   char **decomposed_path;
05433   dbus_bool_t retval;
05434   _dbus_return_val_if_fail (connection != NULL, FALSE);
05435   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05436   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05437   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05438 
05439   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05440     return FALSE;
05441 
05442   CONNECTION_LOCK (connection);
05443 
05444   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05445                                                          (const char **) decomposed_path,
05446                                                          child_entries);
05447   dbus_free_string_array (decomposed_path);
05448 
05449   return retval;
05450 }
05451 
05452 static DBusDataSlotAllocator slot_allocator;
05453 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05454 
05469 dbus_bool_t
05470 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05471 {
05472   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05473                                           &_DBUS_LOCK_NAME (connection_slots),
05474                                           slot_p);
05475 }
05476 
05488 void
05489 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05490 {
05491   _dbus_return_if_fail (*slot_p >= 0);
05492   
05493   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05494 }
05495 
05509 dbus_bool_t
05510 dbus_connection_set_data (DBusConnection   *connection,
05511                           dbus_int32_t      slot,
05512                           void             *data,
05513                           DBusFreeFunction  free_data_func)
05514 {
05515   DBusFreeFunction old_free_func;
05516   void *old_data;
05517   dbus_bool_t retval;
05518 
05519   _dbus_return_val_if_fail (connection != NULL, FALSE);
05520   _dbus_return_val_if_fail (slot >= 0, FALSE);
05521   
05522   CONNECTION_LOCK (connection);
05523 
05524   retval = _dbus_data_slot_list_set (&slot_allocator,
05525                                      &connection->slot_list,
05526                                      slot, data, free_data_func,
05527                                      &old_free_func, &old_data);
05528   
05529   CONNECTION_UNLOCK (connection);
05530 
05531   if (retval)
05532     {
05533       /* Do the actual free outside the connection lock */
05534       if (old_free_func)
05535         (* old_free_func) (old_data);
05536     }
05537 
05538   return retval;
05539 }
05540 
05549 void*
05550 dbus_connection_get_data (DBusConnection   *connection,
05551                           dbus_int32_t      slot)
05552 {
05553   void *res;
05554 
05555   _dbus_return_val_if_fail (connection != NULL, NULL);
05556   
05557   CONNECTION_LOCK (connection);
05558 
05559   res = _dbus_data_slot_list_get (&slot_allocator,
05560                                   &connection->slot_list,
05561                                   slot);
05562   
05563   CONNECTION_UNLOCK (connection);
05564 
05565   return res;
05566 }
05567 
05574 void
05575 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05576 {  
05577   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05578 }
05579 
05588 void
05589 dbus_connection_set_max_message_size (DBusConnection *connection,
05590                                       long            size)
05591 {
05592   _dbus_return_if_fail (connection != NULL);
05593   
05594   CONNECTION_LOCK (connection);
05595   _dbus_transport_set_max_message_size (connection->transport,
05596                                         size);
05597   CONNECTION_UNLOCK (connection);
05598 }
05599 
05606 long
05607 dbus_connection_get_max_message_size (DBusConnection *connection)
05608 {
05609   long res;
05610 
05611   _dbus_return_val_if_fail (connection != NULL, 0);
05612   
05613   CONNECTION_LOCK (connection);
05614   res = _dbus_transport_get_max_message_size (connection->transport);
05615   CONNECTION_UNLOCK (connection);
05616   return res;
05617 }
05618 
05644 void
05645 dbus_connection_set_max_received_size (DBusConnection *connection,
05646                                        long            size)
05647 {
05648   _dbus_return_if_fail (connection != NULL);
05649   
05650   CONNECTION_LOCK (connection);
05651   _dbus_transport_set_max_received_size (connection->transport,
05652                                          size);
05653   CONNECTION_UNLOCK (connection);
05654 }
05655 
05662 long
05663 dbus_connection_get_max_received_size (DBusConnection *connection)
05664 {
05665   long res;
05666 
05667   _dbus_return_val_if_fail (connection != NULL, 0);
05668   
05669   CONNECTION_LOCK (connection);
05670   res = _dbus_transport_get_max_received_size (connection->transport);
05671   CONNECTION_UNLOCK (connection);
05672   return res;
05673 }
05674 
05685 long
05686 dbus_connection_get_outgoing_size (DBusConnection *connection)
05687 {
05688   long res;
05689 
05690   _dbus_return_val_if_fail (connection != NULL, 0);
05691   
05692   CONNECTION_LOCK (connection);
05693   res = _dbus_counter_get_value (connection->outgoing_counter);
05694   CONNECTION_UNLOCK (connection);
05695   return res;
05696 }
05697 

Generated on Mon Feb 1 19:15:25 2010 for D-Bus by  doxygen 1.4.7