dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  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 
00159 typedef struct DBusMessageFilter DBusMessageFilter;
00160 
00164 struct DBusMessageFilter
00165 {
00166   DBusAtomic refcount; 
00167   DBusHandleMessageFunction function; 
00168   void *user_data; 
00169   DBusFreeFunction free_user_data_function; 
00170 };
00171 
00172 
00176 struct DBusPreallocatedSend
00177 {
00178   DBusConnection *connection; 
00179   DBusList *queue_link;       
00180   DBusList *counter_link;     
00181 };
00182 
00183 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00184 
00188 struct DBusConnection
00189 {
00190   DBusAtomic refcount; 
00192   DBusMutex *mutex; 
00194   DBusMutex *dispatch_mutex;     
00195   DBusCondVar *dispatch_cond;    
00196   DBusMutex *io_path_mutex;      
00197   DBusCondVar *io_path_cond;     
00199   DBusList *outgoing_messages; 
00200   DBusList *incoming_messages; 
00202   DBusMessage *message_borrowed; 
00206   int n_outgoing;              
00207   int n_incoming;              
00209   DBusCounter *outgoing_counter; 
00211   DBusTransport *transport;    
00212   DBusWatchList *watches;      
00213   DBusTimeoutList *timeouts;   
00215   DBusList *filter_list;        
00217   DBusDataSlotList slot_list;   
00219   DBusHashTable *pending_replies;  
00221   dbus_uint32_t client_serial;       
00222   DBusList *disconnect_message_link; 
00224   DBusWakeupMainFunction wakeup_main_function; 
00225   void *wakeup_main_data; 
00226   DBusFreeFunction free_wakeup_main_data; 
00228   DBusDispatchStatusFunction dispatch_status_function; 
00229   void *dispatch_status_data; 
00230   DBusFreeFunction free_dispatch_status_data; 
00232   DBusDispatchStatus last_dispatch_status; 
00234   DBusList *link_cache; 
00237   DBusObjectTree *objects; 
00239   char *server_guid; 
00241   unsigned int shareable : 1; 
00243   unsigned int shared : 1; 
00245   unsigned int dispatch_acquired : 1; 
00246   unsigned int io_path_acquired : 1;  
00248   unsigned int exit_on_disconnect : 1; 
00250 #ifndef DBUS_DISABLE_CHECKS
00251   unsigned int have_connection_lock : 1; 
00252 #endif
00253   
00254 #ifndef DBUS_DISABLE_CHECKS
00255   int generation; 
00256 #endif 
00257 };
00258 
00259 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00260 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00261                                                                               DBusDispatchStatus  new_status);
00262 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00263 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00264 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00265 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00266 
00267 static DBusMessageFilter *
00268 _dbus_message_filter_ref (DBusMessageFilter *filter)
00269 {
00270   _dbus_assert (filter->refcount.value > 0);
00271   _dbus_atomic_inc (&filter->refcount);
00272 
00273   return filter;
00274 }
00275 
00276 static void
00277 _dbus_message_filter_unref (DBusMessageFilter *filter)
00278 {
00279   _dbus_assert (filter->refcount.value > 0);
00280 
00281   if (_dbus_atomic_dec (&filter->refcount) == 1)
00282     {
00283       if (filter->free_user_data_function)
00284         (* filter->free_user_data_function) (filter->user_data);
00285       
00286       dbus_free (filter);
00287     }
00288 }
00289 
00295 void
00296 _dbus_connection_lock (DBusConnection *connection)
00297 {
00298   CONNECTION_LOCK (connection);
00299 }
00300 
00306 void
00307 _dbus_connection_unlock (DBusConnection *connection)
00308 {
00309   CONNECTION_UNLOCK (connection);
00310 }
00311 
00319 static void
00320 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00321 {
00322   if (connection->wakeup_main_function)
00323     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00324 }
00325 
00326 #ifdef DBUS_BUILD_TESTS
00327 /* For now this function isn't used */
00337 dbus_bool_t
00338 _dbus_connection_queue_received_message (DBusConnection *connection,
00339                                          DBusMessage    *message)
00340 {
00341   DBusList *link;
00342 
00343   link = _dbus_list_alloc_link (message);
00344   if (link == NULL)
00345     return FALSE;
00346 
00347   dbus_message_ref (message);
00348   _dbus_connection_queue_received_message_link (connection, link);
00349 
00350   return TRUE;
00351 }
00352 
00365 void 
00366 _dbus_connection_test_get_locks (DBusConnection *conn,
00367                                  DBusMutex **mutex_loc,
00368                                  DBusMutex **dispatch_mutex_loc,
00369                                  DBusMutex **io_path_mutex_loc,
00370                                  DBusCondVar **dispatch_cond_loc,
00371                                  DBusCondVar **io_path_cond_loc)
00372 {
00373   *mutex_loc = conn->mutex;
00374   *dispatch_mutex_loc = conn->dispatch_mutex;
00375   *io_path_mutex_loc = conn->io_path_mutex; 
00376   *dispatch_cond_loc = conn->dispatch_cond;
00377   *io_path_cond_loc = conn->io_path_cond;
00378 }
00379 #endif
00380 
00389 void
00390 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00391                                               DBusList        *link)
00392 {
00393   DBusPendingCall *pending;
00394   dbus_int32_t reply_serial;
00395   DBusMessage *message;
00396   
00397   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00398   
00399   _dbus_list_append_link (&connection->incoming_messages,
00400                           link);
00401   message = link->data;
00402 
00403   /* If this is a reply we're waiting on, remove timeout for it */
00404   reply_serial = dbus_message_get_reply_serial (message);
00405   if (reply_serial != -1)
00406     {
00407       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00408                                              reply_serial);
00409       if (pending != NULL)
00410         {
00411           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00412             _dbus_connection_remove_timeout_unlocked (connection,
00413                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00414 
00415           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00416         }
00417     }
00418   
00419   
00420 
00421   connection->n_incoming += 1;
00422 
00423   _dbus_connection_wakeup_mainloop (connection);
00424   
00425   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00426                  message,
00427                  dbus_message_get_type (message),
00428                  dbus_message_get_path (message) ?
00429                  dbus_message_get_path (message) :
00430                  "no path",
00431                  dbus_message_get_interface (message) ?
00432                  dbus_message_get_interface (message) :
00433                  "no interface",
00434                  dbus_message_get_member (message) ?
00435                  dbus_message_get_member (message) :
00436                  "no member",
00437                  dbus_message_get_signature (message),
00438                  dbus_message_get_reply_serial (message),
00439                  connection,
00440                  connection->n_incoming);}
00441 
00450 void
00451 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00452                                                  DBusList *link)
00453 {
00454   HAVE_LOCK_CHECK (connection);
00455   
00456   _dbus_list_append_link (&connection->incoming_messages, link);
00457 
00458   connection->n_incoming += 1;
00459 
00460   _dbus_connection_wakeup_mainloop (connection);
00461   
00462   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00463                  link->data, connection, connection->n_incoming);
00464 }
00465 
00466 
00474 dbus_bool_t
00475 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00476 {
00477   HAVE_LOCK_CHECK (connection);
00478   return connection->outgoing_messages != NULL;
00479 }
00480 
00487 dbus_bool_t
00488 dbus_connection_has_messages_to_send (DBusConnection *connection)
00489 {
00490   dbus_bool_t v;
00491   
00492   _dbus_return_val_if_fail (connection != NULL, FALSE);
00493 
00494   CONNECTION_LOCK (connection);
00495   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00496   CONNECTION_UNLOCK (connection);
00497 
00498   return v;
00499 }
00500 
00508 DBusMessage*
00509 _dbus_connection_get_message_to_send (DBusConnection *connection)
00510 {
00511   HAVE_LOCK_CHECK (connection);
00512   
00513   return _dbus_list_get_last (&connection->outgoing_messages);
00514 }
00515 
00524 void
00525 _dbus_connection_message_sent (DBusConnection *connection,
00526                                DBusMessage    *message)
00527 {
00528   DBusList *link;
00529 
00530   HAVE_LOCK_CHECK (connection);
00531   
00532   /* This can be called before we even complete authentication, since
00533    * it's called on disconnect to clean up the outgoing queue.
00534    * It's also called as we successfully send each message.
00535    */
00536   
00537   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00538   _dbus_assert (link != NULL);
00539   _dbus_assert (link->data == message);
00540 
00541   /* Save this link in the link cache */
00542   _dbus_list_unlink (&connection->outgoing_messages,
00543                      link);
00544   _dbus_list_prepend_link (&connection->link_cache, link);
00545   
00546   connection->n_outgoing -= 1;
00547 
00548   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00549                  message,
00550                  dbus_message_get_type (message),
00551                  dbus_message_get_path (message) ?
00552                  dbus_message_get_path (message) :
00553                  "no path",
00554                  dbus_message_get_interface (message) ?
00555                  dbus_message_get_interface (message) :
00556                  "no interface",
00557                  dbus_message_get_member (message) ?
00558                  dbus_message_get_member (message) :
00559                  "no member",
00560                  dbus_message_get_signature (message),
00561                  connection, connection->n_outgoing);
00562 
00563   /* Save this link in the link cache also */
00564   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00565                                      &link);
00566   _dbus_list_prepend_link (&connection->link_cache, link);
00567   
00568   dbus_message_unref (message);
00569 }
00570 
00571 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00572                                                   DBusWatch     *watch);
00573 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00574                                                   DBusWatch     *watch);
00575 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00576                                                   DBusWatch     *watch,
00577                                                   dbus_bool_t    enabled);
00578 
00579 static dbus_bool_t
00580 protected_change_watch (DBusConnection         *connection,
00581                         DBusWatch              *watch,
00582                         DBusWatchAddFunction    add_function,
00583                         DBusWatchRemoveFunction remove_function,
00584                         DBusWatchToggleFunction toggle_function,
00585                         dbus_bool_t             enabled)
00586 {
00587   DBusWatchList *watches;
00588   dbus_bool_t retval;
00589   
00590   HAVE_LOCK_CHECK (connection);
00591 
00592   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00593    * drop lock and call out" one; but it has to be propagated up through all callers
00594    */
00595   
00596   watches = connection->watches;
00597   if (watches)
00598     {
00599       connection->watches = NULL;
00600       _dbus_connection_ref_unlocked (connection);
00601       CONNECTION_UNLOCK (connection);
00602 
00603       if (add_function)
00604         retval = (* add_function) (watches, watch);
00605       else if (remove_function)
00606         {
00607           retval = TRUE;
00608           (* remove_function) (watches, watch);
00609         }
00610       else
00611         {
00612           retval = TRUE;
00613           (* toggle_function) (watches, watch, enabled);
00614         }
00615       
00616       CONNECTION_LOCK (connection);
00617       connection->watches = watches;
00618       _dbus_connection_unref_unlocked (connection);
00619 
00620       return retval;
00621     }
00622   else
00623     return FALSE;
00624 }
00625      
00626 
00638 dbus_bool_t
00639 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00640                                      DBusWatch      *watch)
00641 {
00642   return protected_change_watch (connection, watch,
00643                                  _dbus_watch_list_add_watch,
00644                                  NULL, NULL, FALSE);
00645 }
00646 
00656 void
00657 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00658                                         DBusWatch      *watch)
00659 {
00660   protected_change_watch (connection, watch,
00661                           NULL,
00662                           _dbus_watch_list_remove_watch,
00663                           NULL, FALSE);
00664 }
00665 
00676 void
00677 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00678                                         DBusWatch      *watch,
00679                                         dbus_bool_t     enabled)
00680 {
00681   _dbus_assert (watch != NULL);
00682 
00683   protected_change_watch (connection, watch,
00684                           NULL, NULL,
00685                           _dbus_watch_list_toggle_watch,
00686                           enabled);
00687 }
00688 
00689 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00690                                                    DBusTimeout     *timeout);
00691 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00692                                                    DBusTimeout     *timeout);
00693 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00694                                                    DBusTimeout     *timeout,
00695                                                    dbus_bool_t      enabled);
00696 
00697 static dbus_bool_t
00698 protected_change_timeout (DBusConnection           *connection,
00699                           DBusTimeout              *timeout,
00700                           DBusTimeoutAddFunction    add_function,
00701                           DBusTimeoutRemoveFunction remove_function,
00702                           DBusTimeoutToggleFunction toggle_function,
00703                           dbus_bool_t               enabled)
00704 {
00705   DBusTimeoutList *timeouts;
00706   dbus_bool_t retval;
00707   
00708   HAVE_LOCK_CHECK (connection);
00709 
00710   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00711    * drop lock and call out" one; but it has to be propagated up through all callers
00712    */
00713   
00714   timeouts = connection->timeouts;
00715   if (timeouts)
00716     {
00717       connection->timeouts = NULL;
00718       _dbus_connection_ref_unlocked (connection);
00719       CONNECTION_UNLOCK (connection);
00720 
00721       if (add_function)
00722         retval = (* add_function) (timeouts, timeout);
00723       else if (remove_function)
00724         {
00725           retval = TRUE;
00726           (* remove_function) (timeouts, timeout);
00727         }
00728       else
00729         {
00730           retval = TRUE;
00731           (* toggle_function) (timeouts, timeout, enabled);
00732         }
00733       
00734       CONNECTION_LOCK (connection);
00735       connection->timeouts = timeouts;
00736       _dbus_connection_unref_unlocked (connection);
00737 
00738       return retval;
00739     }
00740   else
00741     return FALSE;
00742 }
00743 
00756 dbus_bool_t
00757 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00758                                        DBusTimeout    *timeout)
00759 {
00760   return protected_change_timeout (connection, timeout,
00761                                    _dbus_timeout_list_add_timeout,
00762                                    NULL, NULL, FALSE);
00763 }
00764 
00774 void
00775 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00776                                           DBusTimeout    *timeout)
00777 {
00778   protected_change_timeout (connection, timeout,
00779                             NULL,
00780                             _dbus_timeout_list_remove_timeout,
00781                             NULL, FALSE);
00782 }
00783 
00794 void
00795 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00796                                           DBusTimeout      *timeout,
00797                                           dbus_bool_t       enabled)
00798 {
00799   protected_change_timeout (connection, timeout,
00800                             NULL, NULL,
00801                             _dbus_timeout_list_toggle_timeout,
00802                             enabled);
00803 }
00804 
00805 static dbus_bool_t
00806 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00807                                                DBusPendingCall *pending)
00808 {
00809   dbus_uint32_t reply_serial;
00810   DBusTimeout *timeout;
00811 
00812   HAVE_LOCK_CHECK (connection);
00813 
00814   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00815 
00816   _dbus_assert (reply_serial != 0);
00817 
00818   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00819 
00820   if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00821     return FALSE;
00822   
00823   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00824                                     reply_serial,
00825                                     pending))
00826     {
00827       _dbus_connection_remove_timeout_unlocked (connection, timeout);
00828 
00829       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00830       HAVE_LOCK_CHECK (connection);
00831       return FALSE;
00832     }
00833   
00834   _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00835 
00836   _dbus_pending_call_ref_unlocked (pending);
00837 
00838   HAVE_LOCK_CHECK (connection);
00839   
00840   return TRUE;
00841 }
00842 
00843 static void
00844 free_pending_call_on_hash_removal (void *data)
00845 {
00846   DBusPendingCall *pending;
00847   DBusConnection  *connection;
00848   
00849   if (data == NULL)
00850     return;
00851 
00852   pending = data;
00853 
00854   connection = _dbus_pending_call_get_connection_unlocked (pending);
00855 
00856   HAVE_LOCK_CHECK (connection);
00857   
00858   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00859     {
00860       _dbus_connection_remove_timeout_unlocked (connection,
00861                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00862       
00863       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00864     }
00865 
00866   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00867    * here, but the pending call finalizer could in principle call out to 
00868    * application code so we pretty much have to... some larger code reorg 
00869    * might be needed.
00870    */
00871   _dbus_connection_ref_unlocked (connection);
00872   _dbus_pending_call_unref_and_unlock (pending);
00873   CONNECTION_LOCK (connection);
00874   _dbus_connection_unref_unlocked (connection);
00875 }
00876 
00877 static void
00878 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00879                                                DBusPendingCall *pending)
00880 {
00881   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00882    * say the least.
00883    */
00884   _dbus_hash_table_remove_int (connection->pending_replies,
00885                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00886 }
00887 
00888 static void
00889 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00890                                                  DBusPendingCall *pending)
00891 {
00892   /* The idea here is to avoid finalizing the pending call
00893    * with the lock held, since there's a destroy notifier
00894    * in pending call that goes out to application code.
00895    *
00896    * There's an extra unlock inside the hash table
00897    * "free pending call" function FIXME...
00898    */
00899   _dbus_pending_call_ref_unlocked (pending);
00900   _dbus_hash_table_remove_int (connection->pending_replies,
00901                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00902   _dbus_pending_call_unref_and_unlock (pending);
00903 }
00904 
00913 void
00914 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00915                                       DBusPendingCall *pending)
00916 {
00917   CONNECTION_LOCK (connection);
00918   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00919 }
00920 
00930 static dbus_bool_t
00931 _dbus_connection_acquire_io_path (DBusConnection *connection,
00932                                   int timeout_milliseconds)
00933 {
00934   dbus_bool_t we_acquired;
00935   
00936   HAVE_LOCK_CHECK (connection);
00937 
00938   /* We don't want the connection to vanish */
00939   _dbus_connection_ref_unlocked (connection);
00940 
00941   /* We will only touch io_path_acquired which is protected by our mutex */
00942   CONNECTION_UNLOCK (connection);
00943   
00944   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00945   _dbus_mutex_lock (connection->io_path_mutex);
00946 
00947   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00948                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00949 
00950   we_acquired = FALSE;
00951   
00952   if (connection->io_path_acquired)
00953     {
00954       if (timeout_milliseconds != -1)
00955         {
00956           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00957                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
00958           _dbus_condvar_wait_timeout (connection->io_path_cond,
00959                                       connection->io_path_mutex,
00960                                       timeout_milliseconds);
00961         }
00962       else
00963         {
00964           while (connection->io_path_acquired)
00965             {
00966               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00967               _dbus_condvar_wait (connection->io_path_cond, 
00968                                   connection->io_path_mutex);
00969             }
00970         }
00971     }
00972   
00973   if (!connection->io_path_acquired)
00974     {
00975       we_acquired = TRUE;
00976       connection->io_path_acquired = TRUE;
00977     }
00978   
00979   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00980                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00981 
00982   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00983   _dbus_mutex_unlock (connection->io_path_mutex);
00984 
00985   CONNECTION_LOCK (connection);
00986   
00987   HAVE_LOCK_CHECK (connection);
00988 
00989   _dbus_connection_unref_unlocked (connection);
00990   
00991   return we_acquired;
00992 }
00993 
01001 static void
01002 _dbus_connection_release_io_path (DBusConnection *connection)
01003 {
01004   HAVE_LOCK_CHECK (connection);
01005   
01006   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01007   _dbus_mutex_lock (connection->io_path_mutex);
01008   
01009   _dbus_assert (connection->io_path_acquired);
01010 
01011   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01012                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01013   
01014   connection->io_path_acquired = FALSE;
01015   _dbus_condvar_wake_one (connection->io_path_cond);
01016 
01017   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01018   _dbus_mutex_unlock (connection->io_path_mutex);
01019 }
01020 
01049 void
01050 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01051                                         unsigned int    flags,
01052                                         int             timeout_milliseconds)
01053 {
01054   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01055   
01056   HAVE_LOCK_CHECK (connection);
01057   
01058   if (connection->n_outgoing == 0)
01059     flags &= ~DBUS_ITERATION_DO_WRITING;
01060 
01061   if (_dbus_connection_acquire_io_path (connection,
01062                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01063     {
01064       HAVE_LOCK_CHECK (connection);
01065       
01066       _dbus_transport_do_iteration (connection->transport,
01067                                     flags, timeout_milliseconds);
01068       _dbus_connection_release_io_path (connection);
01069     }
01070 
01071   HAVE_LOCK_CHECK (connection);
01072 
01073   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01074 }
01075 
01085 DBusConnection*
01086 _dbus_connection_new_for_transport (DBusTransport *transport)
01087 {
01088   DBusConnection *connection;
01089   DBusWatchList *watch_list;
01090   DBusTimeoutList *timeout_list;
01091   DBusHashTable *pending_replies;
01092   DBusList *disconnect_link;
01093   DBusMessage *disconnect_message;
01094   DBusCounter *outgoing_counter;
01095   DBusObjectTree *objects;
01096   
01097   watch_list = NULL;
01098   connection = NULL;
01099   pending_replies = NULL;
01100   timeout_list = NULL;
01101   disconnect_link = NULL;
01102   disconnect_message = NULL;
01103   outgoing_counter = NULL;
01104   objects = NULL;
01105   
01106   watch_list = _dbus_watch_list_new ();
01107   if (watch_list == NULL)
01108     goto error;
01109 
01110   timeout_list = _dbus_timeout_list_new ();
01111   if (timeout_list == NULL)
01112     goto error;  
01113 
01114   pending_replies =
01115     _dbus_hash_table_new (DBUS_HASH_INT,
01116                           NULL,
01117                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01118   if (pending_replies == NULL)
01119     goto error;
01120   
01121   connection = dbus_new0 (DBusConnection, 1);
01122   if (connection == NULL)
01123     goto error;
01124 
01125   _dbus_mutex_new_at_location (&connection->mutex);
01126   if (connection->mutex == NULL)
01127     goto error;
01128 
01129   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01130   if (connection->io_path_mutex == NULL)
01131     goto error;
01132 
01133   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01134   if (connection->dispatch_mutex == NULL)
01135     goto error;
01136   
01137   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01138   if (connection->dispatch_cond == NULL)
01139     goto error;
01140   
01141   _dbus_condvar_new_at_location (&connection->io_path_cond);
01142   if (connection->io_path_cond == NULL)
01143     goto error;
01144 
01145   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01146                                                 DBUS_INTERFACE_LOCAL,
01147                                                 "Disconnected");
01148   
01149   if (disconnect_message == NULL)
01150     goto error;
01151 
01152   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01153   if (disconnect_link == NULL)
01154     goto error;
01155 
01156   outgoing_counter = _dbus_counter_new ();
01157   if (outgoing_counter == NULL)
01158     goto error;
01159 
01160   objects = _dbus_object_tree_new (connection);
01161   if (objects == NULL)
01162     goto error;
01163   
01164   if (_dbus_modify_sigpipe)
01165     _dbus_disable_sigpipe ();
01166   
01167   connection->refcount.value = 1;
01168   connection->transport = transport;
01169   connection->watches = watch_list;
01170   connection->timeouts = timeout_list;
01171   connection->pending_replies = pending_replies;
01172   connection->outgoing_counter = outgoing_counter;
01173   connection->filter_list = NULL;
01174   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01175   connection->objects = objects;
01176   connection->exit_on_disconnect = FALSE;
01177   connection->shareable = FALSE;
01178 #ifndef DBUS_DISABLE_CHECKS
01179   connection->generation = _dbus_current_generation;
01180 #endif
01181   
01182   _dbus_data_slot_list_init (&connection->slot_list);
01183 
01184   connection->client_serial = 1;
01185 
01186   connection->disconnect_message_link = disconnect_link;
01187 
01188   CONNECTION_LOCK (connection);
01189   
01190   if (!_dbus_transport_set_connection (transport, connection))
01191     {
01192       CONNECTION_UNLOCK (connection);
01193 
01194       goto error;
01195     }
01196 
01197   _dbus_transport_ref (transport);
01198 
01199   CONNECTION_UNLOCK (connection);
01200   
01201   return connection;
01202   
01203  error:
01204   if (disconnect_message != NULL)
01205     dbus_message_unref (disconnect_message);
01206   
01207   if (disconnect_link != NULL)
01208     _dbus_list_free_link (disconnect_link);
01209   
01210   if (connection != NULL)
01211     {
01212       _dbus_condvar_free_at_location (&connection->io_path_cond);
01213       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01214       _dbus_mutex_free_at_location (&connection->mutex);
01215       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01216       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01217       dbus_free (connection);
01218     }
01219   if (pending_replies)
01220     _dbus_hash_table_unref (pending_replies);
01221   
01222   if (watch_list)
01223     _dbus_watch_list_free (watch_list);
01224 
01225   if (timeout_list)
01226     _dbus_timeout_list_free (timeout_list);
01227 
01228   if (outgoing_counter)
01229     _dbus_counter_unref (outgoing_counter);
01230 
01231   if (objects)
01232     _dbus_object_tree_unref (objects);
01233   
01234   return NULL;
01235 }
01236 
01244 DBusConnection *
01245 _dbus_connection_ref_unlocked (DBusConnection *connection)
01246 {  
01247   _dbus_assert (connection != NULL);
01248   _dbus_assert (connection->generation == _dbus_current_generation);
01249 
01250   HAVE_LOCK_CHECK (connection);
01251   
01252 #ifdef DBUS_HAVE_ATOMIC_INT
01253   _dbus_atomic_inc (&connection->refcount);
01254 #else
01255   _dbus_assert (connection->refcount.value > 0);
01256   connection->refcount.value += 1;
01257 #endif
01258 
01259   return connection;
01260 }
01261 
01268 void
01269 _dbus_connection_unref_unlocked (DBusConnection *connection)
01270 {
01271   dbus_bool_t last_unref;
01272 
01273   HAVE_LOCK_CHECK (connection);
01274   
01275   _dbus_assert (connection != NULL);
01276 
01277   /* The connection lock is better than the global
01278    * lock in the atomic increment fallback
01279    */
01280   
01281 #ifdef DBUS_HAVE_ATOMIC_INT
01282   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01283 #else
01284   _dbus_assert (connection->refcount.value > 0);
01285 
01286   connection->refcount.value -= 1;
01287   last_unref = (connection->refcount.value == 0);  
01288 #if 0
01289   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01290 #endif
01291 #endif
01292   
01293   if (last_unref)
01294     _dbus_connection_last_unref (connection);
01295 }
01296 
01297 static dbus_uint32_t
01298 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01299 {
01300   int serial;
01301 
01302   serial = connection->client_serial++;
01303 
01304   if (connection->client_serial < 0)
01305     connection->client_serial = 1;
01306   
01307   return serial;
01308 }
01309 
01323 dbus_bool_t
01324 _dbus_connection_handle_watch (DBusWatch                   *watch,
01325                                unsigned int                 condition,
01326                                void                        *data)
01327 {
01328   DBusConnection *connection;
01329   dbus_bool_t retval;
01330   DBusDispatchStatus status;
01331 
01332   connection = data;
01333 
01334   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01335   
01336   CONNECTION_LOCK (connection);
01337   _dbus_connection_acquire_io_path (connection, -1);
01338   HAVE_LOCK_CHECK (connection);
01339   retval = _dbus_transport_handle_watch (connection->transport,
01340                                          watch, condition);
01341 
01342   _dbus_connection_release_io_path (connection);
01343 
01344   HAVE_LOCK_CHECK (connection);
01345 
01346   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01347   
01348   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01349 
01350   /* this calls out to user code */
01351   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01352 
01353   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01354   
01355   return retval;
01356 }
01357 
01358 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01359 static DBusHashTable *shared_connections = NULL;
01360 
01361 static void
01362 shared_connections_shutdown (void *data)
01363 {
01364   _DBUS_LOCK (shared_connections);
01365 
01366   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01367 
01368   _dbus_hash_table_unref (shared_connections);
01369   shared_connections = NULL;
01370   
01371   _DBUS_UNLOCK (shared_connections);
01372 }
01373 
01374 static dbus_bool_t
01375 connection_lookup_shared (DBusAddressEntry  *entry,
01376                           DBusConnection   **result)
01377 {
01378   _dbus_verbose ("checking for existing connection\n");
01379   
01380   *result = NULL;
01381   
01382   _DBUS_LOCK (shared_connections);
01383 
01384   if (shared_connections == NULL)
01385     {
01386       _dbus_verbose ("creating shared_connections hash table\n");
01387       
01388       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01389                                                  dbus_free,
01390                                                  NULL);
01391       if (shared_connections == NULL)
01392         {
01393           _DBUS_UNLOCK (shared_connections);
01394           return FALSE;
01395         }
01396 
01397       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01398         {
01399           _dbus_hash_table_unref (shared_connections);
01400           shared_connections = NULL;
01401           _DBUS_UNLOCK (shared_connections);
01402           return FALSE;
01403         }
01404 
01405       _dbus_verbose ("  successfully created shared_connections\n");
01406       
01407       _DBUS_UNLOCK (shared_connections);
01408       return TRUE; /* no point looking up in the hash we just made */
01409     }
01410   else
01411     {
01412       const char *guid;
01413 
01414       guid = dbus_address_entry_get_value (entry, "guid");
01415       
01416       if (guid != NULL)
01417         {
01418           *result = _dbus_hash_table_lookup_string (shared_connections,
01419                                                     guid);
01420 
01421           if (*result)
01422             {
01423               /* The DBusConnection can't have been disconnected
01424                * between the lookup and this code, because the
01425                * disconnection will take the shared_connections lock to
01426                * remove the connection. It can't have been finalized
01427                * since you have to disconnect prior to finalize.
01428                *
01429                * Thus it's safe to ref the connection.
01430                */
01431               dbus_connection_ref (*result);
01432 
01433               _dbus_verbose ("looked up existing connection to server guid %s\n",
01434                              guid);
01435             }
01436         }
01437       
01438       _DBUS_UNLOCK (shared_connections);
01439       return TRUE;
01440     }
01441 }
01442 
01443 static dbus_bool_t
01444 connection_record_shared_unlocked (DBusConnection *connection,
01445                                    const char     *guid)
01446 {
01447   char *guid_key;
01448   char *guid_in_connection;
01449 
01450   /* A separate copy of the key is required in the hash table, because
01451    * we don't have a lock on the connection when we are doing a hash
01452    * lookup.
01453    */
01454   
01455   _dbus_assert (connection->server_guid == NULL);
01456   _dbus_assert (connection->shareable);
01457   
01458   guid_key = _dbus_strdup (guid);
01459   if (guid_key == NULL)
01460     return FALSE;
01461 
01462   guid_in_connection = _dbus_strdup (guid);
01463   if (guid_in_connection == NULL)
01464     {
01465       dbus_free (guid_key);
01466       return FALSE;
01467     }
01468   
01469   _DBUS_LOCK (shared_connections);
01470   _dbus_assert (shared_connections != NULL);
01471   
01472   if (!_dbus_hash_table_insert_string (shared_connections,
01473                                        guid_key, connection))
01474     {
01475       dbus_free (guid_key);
01476       dbus_free (guid_in_connection);
01477       _DBUS_UNLOCK (shared_connections);
01478       return FALSE;
01479     }
01480 
01481   connection->server_guid = guid_in_connection;
01482   connection->shared = TRUE;
01483 
01484   /* get a hard ref on this connection */
01485   dbus_connection_ref (connection);
01486 
01487   _dbus_verbose ("stored connection to %s to be shared\n",
01488                  connection->server_guid);
01489   
01490   _DBUS_UNLOCK (shared_connections);
01491 
01492   _dbus_assert (connection->server_guid != NULL);
01493   
01494   return TRUE;
01495 }
01496 
01497 static void
01498 connection_forget_shared_unlocked (DBusConnection *connection)
01499 {
01500   HAVE_LOCK_CHECK (connection);
01501  
01502   if (connection->server_guid == NULL)
01503     return;
01504 
01505   _dbus_verbose ("dropping connection to %s out of the shared table\n",
01506                  connection->server_guid);
01507   
01508   _DBUS_LOCK (shared_connections);
01509 
01510   if (!_dbus_hash_table_remove_string (shared_connections,
01511                                        connection->server_guid))
01512     _dbus_assert_not_reached ("connection was not in the shared table");
01513   
01514   dbus_free (connection->server_guid);
01515   connection->server_guid = NULL;
01516 
01517   /* remove the hash ref */
01518   _dbus_connection_unref_unlocked (connection);
01519   _DBUS_UNLOCK (shared_connections);
01520 }
01521 
01522 static DBusConnection*
01523 connection_try_from_address_entry (DBusAddressEntry *entry,
01524                                    DBusError        *error)
01525 {
01526   DBusTransport *transport;
01527   DBusConnection *connection;
01528 
01529   transport = _dbus_transport_open (entry, error);
01530 
01531   if (transport == NULL)
01532     {
01533       _DBUS_ASSERT_ERROR_IS_SET (error);
01534       return NULL;
01535     }
01536 
01537   connection = _dbus_connection_new_for_transport (transport);
01538 
01539   _dbus_transport_unref (transport);
01540   
01541   if (connection == NULL)
01542     {
01543       _DBUS_SET_OOM (error);
01544       return NULL;
01545     }
01546 
01547 #ifndef DBUS_DISABLE_CHECKS
01548   _dbus_assert (!connection->have_connection_lock);
01549 #endif
01550   return connection;
01551 }
01552 
01553 /*
01554  * If the shared parameter is true, then any existing connection will
01555  * be used (and if a new connection is created, it will be available
01556  * for use by others). If the shared parameter is false, a new
01557  * connection will always be created, and the new connection will
01558  * never be returned to other callers.
01559  *
01560  * @param address the address
01561  * @param shared whether the connection is shared or private
01562  * @param error error return
01563  * @returns the connection or #NULL on error
01564  */
01565 static DBusConnection*
01566 _dbus_connection_open_internal (const char     *address,
01567                                 dbus_bool_t     shared,
01568                                 DBusError      *error)
01569 {
01570   DBusConnection *connection;
01571   DBusAddressEntry **entries;
01572   DBusError tmp_error;
01573   DBusError first_error;
01574   int len, i;
01575 
01576   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01577 
01578   _dbus_verbose ("opening %s connection to: %s\n",
01579                  shared ? "shared" : "private", address);
01580   
01581   if (!dbus_parse_address (address, &entries, &len, error))
01582     return NULL;
01583 
01584   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01585   
01586   connection = NULL;
01587 
01588   dbus_error_init (&tmp_error);
01589   dbus_error_init (&first_error);
01590   for (i = 0; i < len; i++)
01591     {
01592       if (shared)
01593         {
01594           if (!connection_lookup_shared (entries[i], &connection))
01595             _DBUS_SET_OOM (&tmp_error);
01596         }
01597 
01598       if (connection == NULL)
01599         {
01600           connection = connection_try_from_address_entry (entries[i],
01601                                                           &tmp_error);
01602           
01603           if (connection != NULL && shared)
01604             {
01605               const char *guid;
01606 
01607               connection->shareable = TRUE;
01608               
01609               guid = dbus_address_entry_get_value (entries[i], "guid");
01610 
01611               /* we don't have a connection lock but we know nobody
01612                * else has a handle to the connection
01613                */
01614               
01615               if (guid &&
01616                   !connection_record_shared_unlocked (connection, guid))
01617                 {
01618                   _DBUS_SET_OOM (&tmp_error);
01619                   _dbus_connection_close_internal (connection);
01620                   dbus_connection_unref (connection);
01621                   connection = NULL;
01622                 }
01623 
01624               /* but as of now the connection is possibly shared
01625                * since another thread could have pulled it from the table
01626                */
01627             }
01628         }
01629       
01630       if (connection)
01631         break;
01632 
01633       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01634       
01635       if (i == 0)
01636         dbus_move_error (&tmp_error, &first_error);
01637       else
01638         dbus_error_free (&tmp_error);
01639     }
01640 
01641   /* NOTE we don't have a lock on a possibly-shared connection object */
01642   
01643   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01644   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01645   
01646   if (connection == NULL)
01647     {
01648       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01649       dbus_move_error (&first_error, error);
01650     }
01651   else
01652     {
01653       dbus_error_free (&first_error);
01654     }
01655   
01656   dbus_address_entries_free (entries);
01657   return connection;
01658 }
01659 
01687 DBusConnection*
01688 dbus_connection_open (const char     *address,
01689                       DBusError      *error)
01690 {
01691   DBusConnection *connection;
01692 
01693   _dbus_return_val_if_fail (address != NULL, NULL);
01694   _dbus_return_val_if_error_is_set (error, NULL);
01695 
01696   connection = _dbus_connection_open_internal (address,
01697                                                TRUE,
01698                                                error);
01699 
01700   return connection;
01701 }
01702 
01717 DBusConnection*
01718 dbus_connection_open_private (const char     *address,
01719                               DBusError      *error)
01720 {
01721   DBusConnection *connection;
01722 
01723   _dbus_return_val_if_fail (address != NULL, NULL);
01724   _dbus_return_val_if_error_is_set (error, NULL);
01725 
01726   connection = _dbus_connection_open_internal (address,
01727                                                FALSE,
01728                                                error);
01729 
01730   return connection;
01731 }
01732 
01739 DBusConnection *
01740 dbus_connection_ref (DBusConnection *connection)
01741 {
01742   _dbus_return_val_if_fail (connection != NULL, NULL);
01743   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01744   
01745   /* The connection lock is better than the global
01746    * lock in the atomic increment fallback
01747    */
01748   
01749 #ifdef DBUS_HAVE_ATOMIC_INT
01750   _dbus_atomic_inc (&connection->refcount);
01751 #else
01752   CONNECTION_LOCK (connection);
01753   _dbus_assert (connection->refcount.value > 0);
01754 
01755   connection->refcount.value += 1;
01756   CONNECTION_UNLOCK (connection);
01757 #endif
01758 
01759   return connection;
01760 }
01761 
01762 static void
01763 free_outgoing_message (void *element,
01764                        void *data)
01765 {
01766   DBusMessage *message = element;
01767   DBusConnection *connection = data;
01768 
01769   _dbus_message_remove_size_counter (message,
01770                                      connection->outgoing_counter,
01771                                      NULL);
01772   dbus_message_unref (message);
01773 }
01774 
01775 /* This is run without the mutex held, but after the last reference
01776  * to the connection has been dropped we should have no thread-related
01777  * problems
01778  */
01779 static void
01780 _dbus_connection_last_unref (DBusConnection *connection)
01781 {
01782   DBusList *link;
01783 
01784   _dbus_verbose ("Finalizing connection %p\n", connection);
01785   
01786   _dbus_assert (connection->refcount.value == 0);
01787   
01788   /* You have to disconnect the connection before unref:ing it. Otherwise
01789    * you won't get the disconnected message.
01790    */
01791   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01792   _dbus_assert (connection->server_guid == NULL);
01793   
01794   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01795   _dbus_object_tree_free_all_unlocked (connection->objects);
01796   
01797   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01798   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01799   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01800   
01801   _dbus_watch_list_free (connection->watches);
01802   connection->watches = NULL;
01803   
01804   _dbus_timeout_list_free (connection->timeouts);
01805   connection->timeouts = NULL;
01806 
01807   _dbus_data_slot_list_free (&connection->slot_list);
01808   
01809   link = _dbus_list_get_first_link (&connection->filter_list);
01810   while (link != NULL)
01811     {
01812       DBusMessageFilter *filter = link->data;
01813       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01814 
01815       filter->function = NULL;
01816       _dbus_message_filter_unref (filter); /* calls app callback */
01817       link->data = NULL;
01818       
01819       link = next;
01820     }
01821   _dbus_list_clear (&connection->filter_list);
01822   
01823   /* ---- Done with stuff that invokes application callbacks */
01824 
01825   _dbus_object_tree_unref (connection->objects);  
01826 
01827   _dbus_hash_table_unref (connection->pending_replies);
01828   connection->pending_replies = NULL;
01829   
01830   _dbus_list_clear (&connection->filter_list);
01831   
01832   _dbus_list_foreach (&connection->outgoing_messages,
01833                       free_outgoing_message,
01834                       connection);
01835   _dbus_list_clear (&connection->outgoing_messages);
01836   
01837   _dbus_list_foreach (&connection->incoming_messages,
01838                       (DBusForeachFunction) dbus_message_unref,
01839                       NULL);
01840   _dbus_list_clear (&connection->incoming_messages);
01841 
01842   _dbus_counter_unref (connection->outgoing_counter);
01843 
01844   _dbus_transport_unref (connection->transport);
01845 
01846   if (connection->disconnect_message_link)
01847     {
01848       DBusMessage *message = connection->disconnect_message_link->data;
01849       dbus_message_unref (message);
01850       _dbus_list_free_link (connection->disconnect_message_link);
01851     }
01852 
01853   _dbus_list_clear (&connection->link_cache);
01854   
01855   _dbus_condvar_free_at_location (&connection->dispatch_cond);
01856   _dbus_condvar_free_at_location (&connection->io_path_cond);
01857 
01858   _dbus_mutex_free_at_location (&connection->io_path_mutex);
01859   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01860 
01861   _dbus_mutex_free_at_location (&connection->mutex);
01862   
01863   dbus_free (connection);
01864 }
01865 
01877 void
01878 dbus_connection_unref (DBusConnection *connection)
01879 {
01880   dbus_bool_t last_unref;
01881 
01882   _dbus_return_if_fail (connection != NULL);
01883   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01884   
01885   /* The connection lock is better than the global
01886    * lock in the atomic increment fallback
01887    */
01888   
01889 #ifdef DBUS_HAVE_ATOMIC_INT
01890   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01891 #else
01892   CONNECTION_LOCK (connection);
01893   
01894   _dbus_assert (connection->refcount.value > 0);
01895 
01896   connection->refcount.value -= 1;
01897   last_unref = (connection->refcount.value == 0);
01898 
01899 #if 0
01900   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01901 #endif
01902   
01903   CONNECTION_UNLOCK (connection);
01904 #endif
01905   
01906   if (last_unref)
01907     _dbus_connection_last_unref (connection);
01908 }
01909 
01910 static void
01911 _dbus_connection_close_internal_and_unlock (DBusConnection *connection)
01912 {
01913   DBusDispatchStatus status;
01914   
01915   _dbus_verbose ("Disconnecting %p\n", connection);
01916   
01917   _dbus_transport_disconnect (connection->transport);
01918 
01919   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01920   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01921 
01922   /* this calls out to user code */
01923   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01924 }
01925 
01926 void
01927 _dbus_connection_close_internal (DBusConnection *connection)
01928 {
01929   _dbus_assert (connection != NULL);
01930   _dbus_assert (connection->generation == _dbus_current_generation);
01931 
01932   CONNECTION_LOCK (connection);
01933   _dbus_connection_close_internal_and_unlock (connection);
01934 }
01935 
01953 void
01954 dbus_connection_close (DBusConnection *connection)
01955 {
01956   _dbus_return_if_fail (connection != NULL);
01957   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01958 
01959   CONNECTION_LOCK (connection);
01960 
01961   if (connection->shared)
01962     {
01963       CONNECTION_UNLOCK (connection);
01964 
01965       _dbus_warn ("Applications can not close shared connections.  Please fix this in your app.  Ignoring close request and continuing.");
01966       return;
01967     }
01968 
01969   _dbus_connection_close_internal_and_unlock (connection);
01970 }
01971 
01972 static dbus_bool_t
01973 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01974 {
01975   HAVE_LOCK_CHECK (connection);
01976   return _dbus_transport_get_is_connected (connection->transport);
01977 }
01978 
01989 dbus_bool_t
01990 dbus_connection_get_is_connected (DBusConnection *connection)
01991 {
01992   dbus_bool_t res;
01993 
01994   _dbus_return_val_if_fail (connection != NULL, FALSE);
01995   
01996   CONNECTION_LOCK (connection);
01997   res = _dbus_connection_get_is_connected_unlocked (connection);
01998   CONNECTION_UNLOCK (connection);
01999   
02000   return res;
02001 }
02002 
02011 dbus_bool_t
02012 dbus_connection_get_is_authenticated (DBusConnection *connection)
02013 {
02014   dbus_bool_t res;
02015 
02016   _dbus_return_val_if_fail (connection != NULL, FALSE);
02017   
02018   CONNECTION_LOCK (connection);
02019   res = _dbus_transport_get_is_authenticated (connection->transport);
02020   CONNECTION_UNLOCK (connection);
02021   
02022   return res;
02023 }
02024 
02038 void
02039 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02040                                         dbus_bool_t     exit_on_disconnect)
02041 {
02042   _dbus_return_if_fail (connection != NULL);
02043 
02044   CONNECTION_LOCK (connection);
02045   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02046   CONNECTION_UNLOCK (connection);
02047 }
02048 
02049 static DBusPreallocatedSend*
02050 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02051 {
02052   DBusPreallocatedSend *preallocated;
02053 
02054   HAVE_LOCK_CHECK (connection);
02055   
02056   _dbus_assert (connection != NULL);
02057   
02058   preallocated = dbus_new (DBusPreallocatedSend, 1);
02059   if (preallocated == NULL)
02060     return NULL;
02061 
02062   if (connection->link_cache != NULL)
02063     {
02064       preallocated->queue_link =
02065         _dbus_list_pop_first_link (&connection->link_cache);
02066       preallocated->queue_link->data = NULL;
02067     }
02068   else
02069     {
02070       preallocated->queue_link = _dbus_list_alloc_link (NULL);
02071       if (preallocated->queue_link == NULL)
02072         goto failed_0;
02073     }
02074   
02075   if (connection->link_cache != NULL)
02076     {
02077       preallocated->counter_link =
02078         _dbus_list_pop_first_link (&connection->link_cache);
02079       preallocated->counter_link->data = connection->outgoing_counter;
02080     }
02081   else
02082     {
02083       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02084       if (preallocated->counter_link == NULL)
02085         goto failed_1;
02086     }
02087 
02088   _dbus_counter_ref (preallocated->counter_link->data);
02089 
02090   preallocated->connection = connection;
02091   
02092   return preallocated;
02093   
02094  failed_1:
02095   _dbus_list_free_link (preallocated->queue_link);
02096  failed_0:
02097   dbus_free (preallocated);
02098   
02099   return NULL;
02100 }
02101 
02111 DBusPreallocatedSend*
02112 dbus_connection_preallocate_send (DBusConnection *connection)
02113 {
02114   DBusPreallocatedSend *preallocated;
02115 
02116   _dbus_return_val_if_fail (connection != NULL, NULL);
02117 
02118   CONNECTION_LOCK (connection);
02119   
02120   preallocated =
02121     _dbus_connection_preallocate_send_unlocked (connection);
02122 
02123   CONNECTION_UNLOCK (connection);
02124 
02125   return preallocated;
02126 }
02127 
02137 void
02138 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02139                                         DBusPreallocatedSend *preallocated)
02140 {
02141   _dbus_return_if_fail (connection != NULL);
02142   _dbus_return_if_fail (preallocated != NULL);  
02143   _dbus_return_if_fail (connection == preallocated->connection);
02144 
02145   _dbus_list_free_link (preallocated->queue_link);
02146   _dbus_counter_unref (preallocated->counter_link->data);
02147   _dbus_list_free_link (preallocated->counter_link);
02148   dbus_free (preallocated);
02149 }
02150 
02151 /* Called with lock held, does not update dispatch status */
02152 static void
02153 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
02154                                                        DBusPreallocatedSend *preallocated,
02155                                                        DBusMessage          *message,
02156                                                        dbus_uint32_t        *client_serial)
02157 {
02158   dbus_uint32_t serial;
02159   const char *sig;
02160 
02161   preallocated->queue_link->data = message;
02162   _dbus_list_prepend_link (&connection->outgoing_messages,
02163                            preallocated->queue_link);
02164 
02165   _dbus_message_add_size_counter_link (message,
02166                                        preallocated->counter_link);
02167 
02168   dbus_free (preallocated);
02169   preallocated = NULL;
02170   
02171   dbus_message_ref (message);
02172   
02173   connection->n_outgoing += 1;
02174 
02175   sig = dbus_message_get_signature (message);
02176   
02177   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02178                  message,
02179                  dbus_message_get_type (message),
02180                  dbus_message_get_path (message) ?
02181                  dbus_message_get_path (message) :
02182                  "no path",
02183                  dbus_message_get_interface (message) ?
02184                  dbus_message_get_interface (message) :
02185                  "no interface",
02186                  dbus_message_get_member (message) ?
02187                  dbus_message_get_member (message) :
02188                  "no member",
02189                  sig,
02190                  dbus_message_get_destination (message) ?
02191                  dbus_message_get_destination (message) :
02192                  "null",
02193                  connection,
02194                  connection->n_outgoing);
02195 
02196   if (dbus_message_get_serial (message) == 0)
02197     {
02198       serial = _dbus_connection_get_next_client_serial (connection);
02199       _dbus_message_set_serial (message, serial);
02200       if (client_serial)
02201         *client_serial = serial;
02202     }
02203   else
02204     {
02205       if (client_serial)
02206         *client_serial = dbus_message_get_serial (message);
02207     }
02208 
02209   _dbus_verbose ("Message %p serial is %u\n",
02210                  message, dbus_message_get_serial (message));
02211   
02212   _dbus_message_lock (message);
02213 
02214   /* Now we need to run an iteration to hopefully just write the messages
02215    * out immediately, and otherwise get them queued up
02216    */
02217   _dbus_connection_do_iteration_unlocked (connection,
02218                                           DBUS_ITERATION_DO_WRITING,
02219                                           -1);
02220 
02221   /* If stuff is still queued up, be sure we wake up the main loop */
02222   if (connection->n_outgoing > 0)
02223     _dbus_connection_wakeup_mainloop (connection);
02224 }
02225 
02226 static void
02227 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02228                                                DBusPreallocatedSend *preallocated,
02229                                                DBusMessage          *message,
02230                                                dbus_uint32_t        *client_serial)
02231 {
02232   DBusDispatchStatus status;
02233 
02234   HAVE_LOCK_CHECK (connection);
02235   
02236   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02237                                                          preallocated,
02238                                                          message, client_serial);
02239 
02240   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02241   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02242 
02243   /* this calls out to user code */
02244   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02245 }
02246 
02259 void
02260 dbus_connection_send_preallocated (DBusConnection       *connection,
02261                                    DBusPreallocatedSend *preallocated,
02262                                    DBusMessage          *message,
02263                                    dbus_uint32_t        *client_serial)
02264 {
02265   _dbus_return_if_fail (connection != NULL);
02266   _dbus_return_if_fail (preallocated != NULL);
02267   _dbus_return_if_fail (message != NULL);
02268   _dbus_return_if_fail (preallocated->connection == connection);
02269   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02270                         dbus_message_get_member (message) != NULL);
02271   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02272                         (dbus_message_get_interface (message) != NULL &&
02273                          dbus_message_get_member (message) != NULL));
02274   
02275   CONNECTION_LOCK (connection);
02276   _dbus_connection_send_preallocated_and_unlock (connection,
02277                                                  preallocated,
02278                                                  message, client_serial);
02279 }
02280 
02281 static dbus_bool_t
02282 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02283                                           DBusMessage    *message,
02284                                           dbus_uint32_t  *client_serial)
02285 {
02286   DBusPreallocatedSend *preallocated;
02287 
02288   _dbus_assert (connection != NULL);
02289   _dbus_assert (message != NULL);
02290   
02291   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02292   if (preallocated == NULL)
02293     return FALSE;
02294 
02295   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02296                                                          preallocated,
02297                                                          message,
02298                                                          client_serial);
02299   return TRUE;
02300 }
02301 
02302 dbus_bool_t
02303 _dbus_connection_send_and_unlock (DBusConnection *connection,
02304                                   DBusMessage    *message,
02305                                   dbus_uint32_t  *client_serial)
02306 {
02307   DBusPreallocatedSend *preallocated;
02308 
02309   _dbus_assert (connection != NULL);
02310   _dbus_assert (message != NULL);
02311   
02312   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02313   if (preallocated == NULL)
02314     {
02315       CONNECTION_UNLOCK (connection);
02316       return FALSE;
02317     }
02318 
02319   _dbus_connection_send_preallocated_and_unlock (connection,
02320                                                  preallocated,
02321                                                  message,
02322                                                  client_serial);
02323   return TRUE;
02324 }
02325 
02344 dbus_bool_t
02345 dbus_connection_send (DBusConnection *connection,
02346                       DBusMessage    *message,
02347                       dbus_uint32_t  *client_serial)
02348 {
02349   _dbus_return_val_if_fail (connection != NULL, FALSE);
02350   _dbus_return_val_if_fail (message != NULL, FALSE);
02351 
02352   CONNECTION_LOCK (connection);
02353 
02354   return _dbus_connection_send_and_unlock (connection,
02355                                            message,
02356                                            client_serial);
02357 }
02358 
02359 static dbus_bool_t
02360 reply_handler_timeout (void *data)
02361 {
02362   DBusConnection *connection;
02363   DBusDispatchStatus status;
02364   DBusPendingCall *pending = data;
02365 
02366   connection = _dbus_pending_call_get_connection_and_lock (pending);
02367 
02368   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02369                                                    connection);
02370   _dbus_connection_remove_timeout_unlocked (connection,
02371                                             _dbus_pending_call_get_timeout_unlocked (pending));
02372   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02373 
02374   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02375   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02376 
02377   /* Unlocks, and calls out to user code */
02378   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02379   
02380   return TRUE;
02381 }
02382 
02420 dbus_bool_t
02421 dbus_connection_send_with_reply (DBusConnection     *connection,
02422                                  DBusMessage        *message,
02423                                  DBusPendingCall   **pending_return,
02424                                  int                 timeout_milliseconds)
02425 {
02426   DBusPendingCall *pending;
02427   dbus_int32_t serial = -1;
02428   DBusDispatchStatus status;
02429 
02430   _dbus_return_val_if_fail (connection != NULL, FALSE);
02431   _dbus_return_val_if_fail (message != NULL, FALSE);
02432   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02433 
02434   if (pending_return)
02435     *pending_return = NULL;
02436 
02437   CONNECTION_LOCK (connection);
02438 
02439    if (!_dbus_connection_get_is_connected_unlocked (connection))
02440     {
02441       CONNECTION_UNLOCK (connection);
02442 
02443       *pending_return = NULL;
02444 
02445       return TRUE;
02446     }
02447 
02448   pending = _dbus_pending_call_new_unlocked (connection,
02449                                              timeout_milliseconds,
02450                                              reply_handler_timeout);
02451 
02452   if (pending == NULL)
02453     {
02454       CONNECTION_UNLOCK (connection);
02455       return FALSE;
02456     }
02457 
02458   /* Assign a serial to the message */
02459   serial = dbus_message_get_serial (message);
02460   if (serial == 0)
02461     {
02462       serial = _dbus_connection_get_next_client_serial (connection);
02463       _dbus_message_set_serial (message, serial);
02464     }
02465 
02466   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
02467     goto error;
02468     
02469   /* Insert the serial in the pending replies hash;
02470    * hash takes a refcount on DBusPendingCall.
02471    * Also, add the timeout.
02472    */
02473   if (!_dbus_connection_attach_pending_call_unlocked (connection,
02474                                                       pending))
02475     goto error;
02476  
02477   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02478     {
02479       _dbus_connection_detach_pending_call_and_unlock (connection,
02480                                                        pending);
02481       goto error_unlocked;
02482     }
02483 
02484   if (pending_return)
02485     *pending_return = pending; /* hand off refcount */
02486   else
02487     {
02488       _dbus_connection_detach_pending_call_unlocked (connection, pending);
02489       /* we still have a ref to the pending call in this case, we unref
02490        * after unlocking, below
02491        */
02492     }
02493 
02494   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02495 
02496   /* this calls out to user code */
02497   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02498 
02499   if (pending_return == NULL)
02500     dbus_pending_call_unref (pending);
02501   
02502   return TRUE;
02503 
02504  error:
02505   CONNECTION_UNLOCK (connection);
02506  error_unlocked:
02507   dbus_pending_call_unref (pending);
02508   return FALSE;
02509 }
02510 
02511 /* This is slightly strange since we can pop a message here without
02512  * the dispatch lock.
02513  */
02514 static DBusMessage*
02515 check_for_reply_unlocked (DBusConnection *connection,
02516                           dbus_uint32_t   client_serial)
02517 {
02518   DBusList *link;
02519 
02520   HAVE_LOCK_CHECK (connection);
02521   
02522   link = _dbus_list_get_first_link (&connection->incoming_messages);
02523 
02524   while (link != NULL)
02525     {
02526       DBusMessage *reply = link->data;
02527 
02528       if (dbus_message_get_reply_serial (reply) == client_serial)
02529         {
02530           _dbus_list_remove_link (&connection->incoming_messages, link);
02531           connection->n_incoming  -= 1;
02532           return reply;
02533         }
02534       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02535     }
02536 
02537   return NULL;
02538 }
02539 
02540 static void
02541 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02542 {
02543    /* We can't iterate over the hash in the normal way since we'll be
02544     * dropping the lock for each item. So we restart the
02545     * iter each time as we drain the hash table.
02546     */
02547    
02548    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02549     {
02550       DBusPendingCall *pending;
02551       DBusHashIter iter;
02552       
02553       _dbus_hash_iter_init (connection->pending_replies, &iter);
02554       _dbus_hash_iter_next (&iter);
02555        
02556       pending = (DBusPendingCall *) _dbus_hash_iter_get_value (&iter);
02557       _dbus_pending_call_ref_unlocked (pending);
02558        
02559       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02560                                                        connection);
02561       _dbus_connection_remove_timeout_unlocked (connection,
02562                                                 _dbus_pending_call_get_timeout_unlocked (pending));
02563       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02564       _dbus_hash_iter_remove_entry (&iter);
02565 
02566       _dbus_pending_call_unref_and_unlock (pending);
02567       CONNECTION_LOCK (connection);
02568     }
02569   HAVE_LOCK_CHECK (connection);
02570 }
02571 
02572 static void
02573 complete_pending_call_and_unlock (DBusConnection  *connection,
02574                                   DBusPendingCall *pending,
02575                                   DBusMessage     *message)
02576 {
02577   _dbus_pending_call_set_reply_unlocked (pending, message);
02578   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02579   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02580  
02581   /* Must be called unlocked since it invokes app callback */
02582   _dbus_pending_call_complete (pending);
02583   dbus_pending_call_unref (pending);
02584 }
02585 
02586 static dbus_bool_t
02587 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02588                                               DBusPendingCall *pending)
02589 {
02590   DBusMessage *reply;
02591   DBusDispatchStatus status;
02592 
02593   reply = check_for_reply_unlocked (connection, 
02594                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02595   if (reply != NULL)
02596     {
02597       _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02598 
02599       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02600 
02601       complete_pending_call_and_unlock (connection, pending, reply);
02602       dbus_message_unref (reply);
02603 
02604       CONNECTION_LOCK (connection);
02605       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02606       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02607       dbus_pending_call_unref (pending);
02608 
02609       return TRUE;
02610     }
02611 
02612   return FALSE;
02613 }
02614 
02624 static void
02625 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02626 {
02627   if (timeout_milliseconds == -1)
02628     _dbus_sleep_milliseconds (1000);
02629   else if (timeout_milliseconds < 100)
02630     ; /* just busy loop */
02631   else if (timeout_milliseconds <= 1000)
02632     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02633   else
02634     _dbus_sleep_milliseconds (1000);
02635 }
02636 
02637 static DBusMessage *
02638 generate_local_error_message (dbus_uint32_t serial, 
02639                               char *error_name, 
02640                               char *error_msg)
02641 {
02642   DBusMessage *message;
02643   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02644   if (!message)
02645     goto out;
02646 
02647   if (!dbus_message_set_error_name (message, error_name))
02648     {
02649       dbus_message_unref (message);
02650       message = NULL;
02651       goto out; 
02652     }
02653 
02654   dbus_message_set_no_reply (message, TRUE); 
02655 
02656   if (!dbus_message_set_reply_serial (message,
02657                                       serial))
02658     {
02659       dbus_message_unref (message);
02660       message = NULL;
02661       goto out;
02662     }
02663 
02664   if (error_msg != NULL)
02665     {
02666       DBusMessageIter iter;
02667 
02668       dbus_message_iter_init_append (message, &iter);
02669       if (!dbus_message_iter_append_basic (&iter,
02670                                            DBUS_TYPE_STRING,
02671                                            &error_msg))
02672         {
02673           dbus_message_unref (message);
02674           message = NULL;
02675           goto out;
02676         }
02677     }
02678 
02679  out:
02680   return message;
02681 }
02682 
02697 void
02698 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02699 {
02700   long start_tv_sec, start_tv_usec;
02701   long end_tv_sec, end_tv_usec;
02702   long tv_sec, tv_usec;
02703   DBusDispatchStatus status;
02704   DBusConnection *connection;
02705   dbus_uint32_t client_serial;
02706   int timeout_milliseconds;
02707 
02708   _dbus_assert (pending != NULL);
02709 
02710   if (dbus_pending_call_get_completed (pending))
02711     return;
02712 
02713   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02714 
02715   connection = _dbus_pending_call_get_connection_and_lock (pending);
02716   
02717   /* Flush message queue - note, can affect dispatch status */
02718   _dbus_connection_flush_unlocked (connection);
02719 
02720   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02721 
02722   /* note that timeout_milliseconds is limited to a smallish value
02723    * in _dbus_pending_call_new() so overflows aren't possible
02724    * below
02725    */
02726   timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02727   
02728   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02729   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02730   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02731   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02732   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02733 
02734   _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",
02735                  timeout_milliseconds,
02736                  client_serial,
02737                  start_tv_sec, start_tv_usec,
02738                  end_tv_sec, end_tv_usec);
02739 
02740   /* check to see if we already got the data off the socket */
02741   /* from another blocked pending call */
02742   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02743     return;
02744 
02745   /* Now we wait... */
02746   /* always block at least once as we know we don't have the reply yet */
02747   _dbus_connection_do_iteration_unlocked (connection,
02748                                           DBUS_ITERATION_DO_READING |
02749                                           DBUS_ITERATION_BLOCK,
02750                                           timeout_milliseconds);
02751 
02752  recheck_status:
02753 
02754   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02755   
02756   HAVE_LOCK_CHECK (connection);
02757   
02758   /* queue messages and get status */
02759 
02760   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02761 
02762   /* the get_completed() is in case a dispatch() while we were blocking
02763    * got the reply instead of us.
02764    */
02765   if (_dbus_pending_call_get_completed_unlocked (pending))
02766     {
02767       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02768       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02769       dbus_pending_call_unref (pending);
02770       return;
02771     }
02772   
02773   if (status == DBUS_DISPATCH_DATA_REMAINS) {
02774     if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02775       return;
02776   }
02777   
02778   _dbus_get_current_time (&tv_sec, &tv_usec);
02779   
02780   if (!_dbus_connection_get_is_connected_unlocked (connection))
02781     {
02782       DBusMessage *error_msg;
02783 
02784       error_msg = generate_local_error_message (client_serial,
02785                                                 DBUS_ERROR_DISCONNECTED, 
02786                                                 "Connection was dissconnected before a reply was recived"); 
02787 
02788       /* on OOM error_msg is set to NULL */
02789       complete_pending_call_and_unlock (connection, pending, error_msg);
02790       dbus_pending_call_unref (pending);
02791       return;
02792     }
02793   else if (tv_sec < start_tv_sec)
02794     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02795   else if (connection->disconnect_message_link == NULL)
02796     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02797   else if (tv_sec < end_tv_sec ||
02798            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02799     {
02800       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02801         (end_tv_usec - tv_usec) / 1000;
02802       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02803       _dbus_assert (timeout_milliseconds >= 0);
02804       
02805       if (status == DBUS_DISPATCH_NEED_MEMORY)
02806         {
02807           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02808            * we may already have a reply in the buffer and just can't process
02809            * it.
02810            */
02811           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02812 
02813           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02814         }
02815       else
02816         {          
02817           /* block again, we don't have the reply buffered yet. */
02818           _dbus_connection_do_iteration_unlocked (connection,
02819                                                   DBUS_ITERATION_DO_READING |
02820                                                   DBUS_ITERATION_BLOCK,
02821                                                   timeout_milliseconds);
02822         }
02823 
02824       goto recheck_status;
02825     }
02826 
02827   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02828                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02829 
02830   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02831   
02832   /* unlock and call user code */
02833   complete_pending_call_and_unlock (connection, pending, NULL);
02834 
02835   /* update user code on dispatch status */
02836   CONNECTION_LOCK (connection);
02837   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02838   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02839   dbus_pending_call_unref (pending);
02840 }
02841 
02864 DBusMessage*
02865 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
02866                                            DBusMessage        *message,
02867                                            int                 timeout_milliseconds,
02868                                            DBusError          *error)
02869 {
02870   DBusMessage *reply;
02871   DBusPendingCall *pending;
02872   
02873   _dbus_return_val_if_fail (connection != NULL, NULL);
02874   _dbus_return_val_if_fail (message != NULL, NULL);
02875   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
02876   _dbus_return_val_if_error_is_set (error, NULL);
02877   
02878   if (!dbus_connection_send_with_reply (connection, message,
02879                                         &pending, timeout_milliseconds))
02880     {
02881       _DBUS_SET_OOM (error);
02882       return NULL;
02883     }
02884 
02885   _dbus_assert (pending != NULL);
02886   
02887   dbus_pending_call_block (pending);
02888 
02889   reply = dbus_pending_call_steal_reply (pending);
02890   dbus_pending_call_unref (pending);
02891 
02892   /* call_complete_and_unlock() called from pending_call_block() should
02893    * always fill this in.
02894    */
02895   _dbus_assert (reply != NULL);
02896   
02897    if (dbus_set_error_from_message (error, reply))
02898     {
02899       dbus_message_unref (reply);
02900       return NULL;
02901     }
02902   else
02903     return reply;
02904 }
02905 
02914 DBusDispatchStatus
02915 _dbus_connection_flush_unlocked (DBusConnection *connection)
02916 {
02917   /* We have to specify DBUS_ITERATION_DO_READING here because
02918    * otherwise we could have two apps deadlock if they are both doing
02919    * a flush(), and the kernel buffers fill up. This could change the
02920    * dispatch status.
02921    */
02922   DBusDispatchStatus status;
02923 
02924   HAVE_LOCK_CHECK (connection);
02925   
02926   while (connection->n_outgoing > 0 &&
02927          _dbus_connection_get_is_connected_unlocked (connection))
02928     {
02929       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02930       HAVE_LOCK_CHECK (connection);
02931       _dbus_connection_do_iteration_unlocked (connection,
02932                                               DBUS_ITERATION_DO_READING |
02933                                               DBUS_ITERATION_DO_WRITING |
02934                                               DBUS_ITERATION_BLOCK,
02935                                               -1);
02936     }
02937 
02938   HAVE_LOCK_CHECK (connection);
02939   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02940   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02941 
02942   HAVE_LOCK_CHECK (connection);
02943   return status;
02944 }
02945 
02951 void
02952 dbus_connection_flush (DBusConnection *connection)
02953 {
02954   /* We have to specify DBUS_ITERATION_DO_READING here because
02955    * otherwise we could have two apps deadlock if they are both doing
02956    * a flush(), and the kernel buffers fill up. This could change the
02957    * dispatch status.
02958    */
02959   DBusDispatchStatus status;
02960 
02961   _dbus_return_if_fail (connection != NULL);
02962   
02963   CONNECTION_LOCK (connection);
02964 
02965   status = _dbus_connection_flush_unlocked (connection);
02966   
02967   HAVE_LOCK_CHECK (connection);
02968   /* Unlocks and calls out to user code */
02969   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02970 
02971   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02972 }
02973 
03006 static dbus_bool_t
03007 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03008                                      int             timeout_milliseconds, 
03009                                      dbus_bool_t     dispatch)
03010 {
03011   DBusDispatchStatus dstatus;
03012   dbus_bool_t dispatched_disconnected;
03013   
03014   dstatus = dbus_connection_get_dispatch_status (connection);
03015 
03016   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03017     {
03018       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03019       dbus_connection_dispatch (connection);
03020       CONNECTION_LOCK (connection);
03021     }
03022   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03023     {
03024       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03025       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03026       CONNECTION_LOCK (connection);
03027     }
03028   else
03029     {
03030       CONNECTION_LOCK (connection);
03031       if (_dbus_connection_get_is_connected_unlocked (connection))
03032         {
03033           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03034           _dbus_connection_do_iteration_unlocked (connection,
03035                                                   DBUS_ITERATION_DO_READING |
03036                                                   DBUS_ITERATION_DO_WRITING |
03037                                                   DBUS_ITERATION_BLOCK,
03038                                                   timeout_milliseconds);
03039         }
03040     }
03041   
03042   HAVE_LOCK_CHECK (connection);
03043   dispatched_disconnected = connection->n_incoming == 0 &&
03044     connection->disconnect_message_link == NULL;
03045   CONNECTION_UNLOCK (connection);
03046   return !dispatched_disconnected; /* TRUE if we have not processed disconnected */
03047 }
03048 
03049 
03081 dbus_bool_t
03082 dbus_connection_read_write_dispatch (DBusConnection *connection,
03083                                      int             timeout_milliseconds)
03084 {
03085   _dbus_return_val_if_fail (connection != NULL, FALSE);
03086   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03087    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03088 }
03089 
03106 dbus_bool_t 
03107 dbus_connection_read_write (DBusConnection *connection, 
03108                             int             timeout_milliseconds) 
03109 { 
03110   _dbus_return_val_if_fail (connection != NULL, FALSE);
03111   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03112    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03113 }
03114 
03134 DBusMessage*
03135 dbus_connection_borrow_message (DBusConnection *connection)
03136 {
03137   DBusDispatchStatus status;
03138   DBusMessage *message;
03139 
03140   _dbus_return_val_if_fail (connection != NULL, NULL);
03141 
03142   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03143   
03144   /* this is called for the side effect that it queues
03145    * up any messages from the transport
03146    */
03147   status = dbus_connection_get_dispatch_status (connection);
03148   if (status != DBUS_DISPATCH_DATA_REMAINS)
03149     return NULL;
03150   
03151   CONNECTION_LOCK (connection);
03152 
03153   _dbus_connection_acquire_dispatch (connection);
03154 
03155   /* While a message is outstanding, the dispatch lock is held */
03156   _dbus_assert (connection->message_borrowed == NULL);
03157 
03158   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03159   
03160   message = connection->message_borrowed;
03161 
03162   /* Note that we KEEP the dispatch lock until the message is returned */
03163   if (message == NULL)
03164     _dbus_connection_release_dispatch (connection);
03165 
03166   CONNECTION_UNLOCK (connection);
03167   
03168   return message;
03169 }
03170 
03179 void
03180 dbus_connection_return_message (DBusConnection *connection,
03181                                 DBusMessage    *message)
03182 {
03183   _dbus_return_if_fail (connection != NULL);
03184   _dbus_return_if_fail (message != NULL);
03185   _dbus_return_if_fail (message == connection->message_borrowed);
03186   _dbus_return_if_fail (connection->dispatch_acquired);
03187   
03188   CONNECTION_LOCK (connection);
03189   
03190   _dbus_assert (message == connection->message_borrowed);
03191   
03192   connection->message_borrowed = NULL;
03193 
03194   _dbus_connection_release_dispatch (connection);
03195   
03196   CONNECTION_UNLOCK (connection);
03197 }
03198 
03208 void
03209 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03210                                         DBusMessage    *message)
03211 {
03212   DBusMessage *pop_message;
03213 
03214   _dbus_return_if_fail (connection != NULL);
03215   _dbus_return_if_fail (message != NULL);
03216   _dbus_return_if_fail (message == connection->message_borrowed);
03217   _dbus_return_if_fail (connection->dispatch_acquired);
03218   
03219   CONNECTION_LOCK (connection);
03220  
03221   _dbus_assert (message == connection->message_borrowed);
03222 
03223   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03224   _dbus_assert (message == pop_message);
03225   
03226   connection->n_incoming -= 1;
03227  
03228   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03229                  message, connection->n_incoming);
03230  
03231   connection->message_borrowed = NULL;
03232 
03233   _dbus_connection_release_dispatch (connection);
03234   
03235   CONNECTION_UNLOCK (connection);
03236 }
03237 
03238 /* See dbus_connection_pop_message, but requires the caller to own
03239  * the lock before calling. May drop the lock while running.
03240  */
03241 static DBusList*
03242 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03243 {
03244   HAVE_LOCK_CHECK (connection);
03245   
03246   _dbus_assert (connection->message_borrowed == NULL);
03247   
03248   if (connection->n_incoming > 0)
03249     {
03250       DBusList *link;
03251 
03252       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03253       connection->n_incoming -= 1;
03254 
03255       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03256                      link->data,
03257                      dbus_message_get_type (link->data),
03258                      dbus_message_get_path (link->data) ?
03259                      dbus_message_get_path (link->data) :
03260                      "no path",
03261                      dbus_message_get_interface (link->data) ?
03262                      dbus_message_get_interface (link->data) :
03263                      "no interface",
03264                      dbus_message_get_member (link->data) ?
03265                      dbus_message_get_member (link->data) :
03266                      "no member",
03267                      dbus_message_get_signature (link->data),
03268                      connection, connection->n_incoming);
03269 
03270       return link;
03271     }
03272   else
03273     return NULL;
03274 }
03275 
03276 /* See dbus_connection_pop_message, but requires the caller to own
03277  * the lock before calling. May drop the lock while running.
03278  */
03279 static DBusMessage*
03280 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03281 {
03282   DBusList *link;
03283 
03284   HAVE_LOCK_CHECK (connection);
03285   
03286   link = _dbus_connection_pop_message_link_unlocked (connection);
03287 
03288   if (link != NULL)
03289     {
03290       DBusMessage *message;
03291       
03292       message = link->data;
03293       
03294       _dbus_list_free_link (link);
03295       
03296       return message;
03297     }
03298   else
03299     return NULL;
03300 }
03301 
03302 static void
03303 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03304                                                 DBusList       *message_link)
03305 {
03306   HAVE_LOCK_CHECK (connection);
03307   
03308   _dbus_assert (message_link != NULL);
03309   /* You can't borrow a message while a link is outstanding */
03310   _dbus_assert (connection->message_borrowed == NULL);
03311   /* We had to have the dispatch lock across the pop/putback */
03312   _dbus_assert (connection->dispatch_acquired);
03313 
03314   _dbus_list_prepend_link (&connection->incoming_messages,
03315                            message_link);
03316   connection->n_incoming += 1;
03317 
03318   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03319                  message_link->data,
03320                  dbus_message_get_type (message_link->data),
03321                  dbus_message_get_interface (message_link->data) ?
03322                  dbus_message_get_interface (message_link->data) :
03323                  "no interface",
03324                  dbus_message_get_member (message_link->data) ?
03325                  dbus_message_get_member (message_link->data) :
03326                  "no member",
03327                  dbus_message_get_signature (message_link->data),
03328                  connection, connection->n_incoming);
03329 }
03330 
03350 DBusMessage*
03351 dbus_connection_pop_message (DBusConnection *connection)
03352 {
03353   DBusMessage *message;
03354   DBusDispatchStatus status;
03355 
03356   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03357   
03358   /* this is called for the side effect that it queues
03359    * up any messages from the transport
03360    */
03361   status = dbus_connection_get_dispatch_status (connection);
03362   if (status != DBUS_DISPATCH_DATA_REMAINS)
03363     return NULL;
03364   
03365   CONNECTION_LOCK (connection);
03366   _dbus_connection_acquire_dispatch (connection);
03367   HAVE_LOCK_CHECK (connection);
03368   
03369   message = _dbus_connection_pop_message_unlocked (connection);
03370 
03371   _dbus_verbose ("Returning popped message %p\n", message);    
03372 
03373   _dbus_connection_release_dispatch (connection);
03374   CONNECTION_UNLOCK (connection);
03375   
03376   return message;
03377 }
03378 
03386 static void
03387 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03388 {
03389   HAVE_LOCK_CHECK (connection);
03390 
03391   _dbus_connection_ref_unlocked (connection);
03392   CONNECTION_UNLOCK (connection);
03393   
03394   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03395   _dbus_mutex_lock (connection->dispatch_mutex);
03396 
03397   while (connection->dispatch_acquired)
03398     {
03399       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03400       _dbus_condvar_wait (connection->dispatch_cond, 
03401                           connection->dispatch_mutex);
03402     }
03403   
03404   _dbus_assert (!connection->dispatch_acquired);
03405 
03406   connection->dispatch_acquired = TRUE;
03407 
03408   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03409   _dbus_mutex_unlock (connection->dispatch_mutex);
03410   
03411   CONNECTION_LOCK (connection);
03412   _dbus_connection_unref_unlocked (connection);
03413 }
03414 
03422 static void
03423 _dbus_connection_release_dispatch (DBusConnection *connection)
03424 {
03425   HAVE_LOCK_CHECK (connection);
03426   
03427   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03428   _dbus_mutex_lock (connection->dispatch_mutex);
03429   
03430   _dbus_assert (connection->dispatch_acquired);
03431 
03432   connection->dispatch_acquired = FALSE;
03433   _dbus_condvar_wake_one (connection->dispatch_cond);
03434 
03435   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03436   _dbus_mutex_unlock (connection->dispatch_mutex);
03437 }
03438 
03439 static void
03440 _dbus_connection_failed_pop (DBusConnection *connection,
03441                              DBusList       *message_link)
03442 {
03443   _dbus_list_prepend_link (&connection->incoming_messages,
03444                            message_link);
03445   connection->n_incoming += 1;
03446 }
03447 
03448 static DBusDispatchStatus
03449 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03450 {
03451   HAVE_LOCK_CHECK (connection);
03452   
03453   if (connection->n_incoming > 0)
03454     return DBUS_DISPATCH_DATA_REMAINS;
03455   else if (!_dbus_transport_queue_messages (connection->transport))
03456     return DBUS_DISPATCH_NEED_MEMORY;
03457   else
03458     {
03459       DBusDispatchStatus status;
03460       dbus_bool_t is_connected;
03461       
03462       status = _dbus_transport_get_dispatch_status (connection->transport);
03463       is_connected = _dbus_transport_get_is_connected (connection->transport);
03464 
03465       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03466                      DISPATCH_STATUS_NAME (status), is_connected);
03467       
03468       if (!is_connected)
03469         {
03470           if (status == DBUS_DISPATCH_COMPLETE &&
03471               connection->disconnect_message_link)
03472             {
03473               _dbus_verbose ("Sending disconnect message from %s\n",
03474                              _DBUS_FUNCTION_NAME);
03475 
03476               connection_forget_shared_unlocked (connection);
03477              
03478               /* If we have pending calls queued timeouts on disconnect */
03479               connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03480  
03481               /* We haven't sent the disconnect message already,
03482                * and all real messages have been queued up.
03483                */
03484               _dbus_connection_queue_synthesized_message_link (connection,
03485                                                                connection->disconnect_message_link);
03486               connection->disconnect_message_link = NULL;
03487 
03488               status = DBUS_DISPATCH_DATA_REMAINS;
03489             }
03490 
03491           /* Dump the outgoing queue, we aren't going to be able to
03492            * send it now, and we'd like accessors like
03493            * dbus_connection_get_outgoing_size() to be accurate.
03494            */
03495           if (connection->n_outgoing > 0)
03496             {
03497               DBusList *link;
03498               
03499               _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03500                              connection->n_outgoing);
03501               
03502               while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03503                 {
03504                   _dbus_connection_message_sent (connection, link->data);
03505                 }
03506             }
03507         }
03508       
03509       if (status != DBUS_DISPATCH_COMPLETE)
03510         return status;
03511       else if (connection->n_incoming > 0)
03512         return DBUS_DISPATCH_DATA_REMAINS;
03513       else
03514         return DBUS_DISPATCH_COMPLETE;
03515     }
03516 }
03517 
03518 static void
03519 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03520                                                     DBusDispatchStatus new_status)
03521 {
03522   dbus_bool_t changed;
03523   DBusDispatchStatusFunction function;
03524   void *data;
03525 
03526   HAVE_LOCK_CHECK (connection);
03527 
03528   _dbus_connection_ref_unlocked (connection);
03529 
03530   changed = new_status != connection->last_dispatch_status;
03531 
03532   connection->last_dispatch_status = new_status;
03533 
03534   function = connection->dispatch_status_function;
03535   data = connection->dispatch_status_data;
03536 
03537   /* We drop the lock */
03538   CONNECTION_UNLOCK (connection);
03539   
03540   if (changed && function)
03541     {
03542       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03543                      connection, new_status,
03544                      DISPATCH_STATUS_NAME (new_status));
03545       (* function) (connection, new_status, data);      
03546     }
03547   
03548   dbus_connection_unref (connection);
03549 }
03550 
03559 DBusDispatchStatus
03560 dbus_connection_get_dispatch_status (DBusConnection *connection)
03561 {
03562   DBusDispatchStatus status;
03563 
03564   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03565 
03566   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03567   
03568   CONNECTION_LOCK (connection);
03569 
03570   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03571   
03572   CONNECTION_UNLOCK (connection);
03573 
03574   return status;
03575 }
03576 
03580 static DBusHandlerResult
03581 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03582                                                  DBusMessage    *message)
03583 {
03584   if (dbus_message_is_method_call (message,
03585                                    DBUS_INTERFACE_PEER,
03586                                    "Ping"))
03587     {
03588       DBusMessage *ret;
03589       dbus_bool_t sent;
03590       
03591       ret = dbus_message_new_method_return (message);
03592       if (ret == NULL)
03593         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03594      
03595       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
03596 
03597       dbus_message_unref (ret);
03598 
03599       if (!sent)
03600         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03601       
03602       return DBUS_HANDLER_RESULT_HANDLED;
03603     }
03604                                    
03605   
03606   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03607 }
03608 
03615 static DBusHandlerResult
03616 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
03617                                                            DBusMessage    *message)
03618 {
03619   /* We just run one filter for now but have the option to run more
03620      if the spec calls for it in the future */
03621 
03622   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
03623 }
03624 
03648 DBusDispatchStatus
03649 dbus_connection_dispatch (DBusConnection *connection)
03650 {
03651   DBusMessage *message;
03652   DBusList *link, *filter_list_copy, *message_link;
03653   DBusHandlerResult result;
03654   DBusPendingCall *pending;
03655   dbus_int32_t reply_serial;
03656   DBusDispatchStatus status;
03657 
03658   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03659 
03660   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03661   
03662   CONNECTION_LOCK (connection);
03663   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03664   if (status != DBUS_DISPATCH_DATA_REMAINS)
03665     {
03666       /* unlocks and calls out to user code */
03667       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03668       return status;
03669     }
03670   
03671   /* We need to ref the connection since the callback could potentially
03672    * drop the last ref to it
03673    */
03674   _dbus_connection_ref_unlocked (connection);
03675 
03676   _dbus_connection_acquire_dispatch (connection);
03677   HAVE_LOCK_CHECK (connection);
03678 
03679   message_link = _dbus_connection_pop_message_link_unlocked (connection);
03680   if (message_link == NULL)
03681     {
03682       /* another thread dispatched our stuff */
03683 
03684       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03685       
03686       _dbus_connection_release_dispatch (connection);
03687 
03688       status = _dbus_connection_get_dispatch_status_unlocked (connection);
03689 
03690       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03691       
03692       dbus_connection_unref (connection);
03693       
03694       return status;
03695     }
03696 
03697   message = message_link->data;
03698 
03699   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03700                  message,
03701                  dbus_message_get_type (message),
03702                  dbus_message_get_interface (message) ?
03703                  dbus_message_get_interface (message) :
03704                  "no interface",
03705                  dbus_message_get_member (message) ?
03706                  dbus_message_get_member (message) :
03707                  "no member",
03708                  dbus_message_get_signature (message));
03709 
03710   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03711   
03712   /* Pending call handling must be first, because if you do
03713    * dbus_connection_send_with_reply_and_block() or
03714    * dbus_pending_call_block() then no handlers/filters will be run on
03715    * the reply. We want consistent semantics in the case where we
03716    * dbus_connection_dispatch() the reply.
03717    */
03718   
03719   reply_serial = dbus_message_get_reply_serial (message);
03720   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03721                                          reply_serial);
03722   if (pending)
03723     {
03724       _dbus_verbose ("Dispatching a pending reply\n");
03725       complete_pending_call_and_unlock (connection, pending, message);
03726       pending = NULL; /* it's probably unref'd */
03727       
03728       CONNECTION_LOCK (connection);
03729       _dbus_verbose ("pending call completed in dispatch\n");
03730       result = DBUS_HANDLER_RESULT_HANDLED;
03731       goto out;
03732     }
03733 
03734   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
03735   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03736     goto out;
03737  
03738   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03739     {
03740       _dbus_connection_release_dispatch (connection);
03741       HAVE_LOCK_CHECK (connection);
03742       
03743       _dbus_connection_failed_pop (connection, message_link);
03744 
03745       /* unlocks and calls user code */
03746       _dbus_connection_update_dispatch_status_and_unlock (connection,
03747                                                           DBUS_DISPATCH_NEED_MEMORY);
03748 
03749       if (pending)
03750         dbus_pending_call_unref (pending);
03751       dbus_connection_unref (connection);
03752       
03753       return DBUS_DISPATCH_NEED_MEMORY;
03754     }
03755   
03756   _dbus_list_foreach (&filter_list_copy,
03757                       (DBusForeachFunction)_dbus_message_filter_ref,
03758                       NULL);
03759 
03760   /* We're still protected from dispatch() reentrancy here
03761    * since we acquired the dispatcher
03762    */
03763   CONNECTION_UNLOCK (connection);
03764   
03765   link = _dbus_list_get_first_link (&filter_list_copy);
03766   while (link != NULL)
03767     {
03768       DBusMessageFilter *filter = link->data;
03769       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03770 
03771       if (filter->function == NULL)
03772         {
03773           _dbus_verbose ("  filter was removed in a callback function\n");
03774           link = next;
03775           continue;
03776         }
03777 
03778       _dbus_verbose ("  running filter on message %p\n", message);
03779       result = (* filter->function) (connection, message, filter->user_data);
03780 
03781       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03782         break;
03783 
03784       link = next;
03785     }
03786 
03787   _dbus_list_foreach (&filter_list_copy,
03788                       (DBusForeachFunction)_dbus_message_filter_unref,
03789                       NULL);
03790   _dbus_list_clear (&filter_list_copy);
03791   
03792   CONNECTION_LOCK (connection);
03793 
03794   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03795     {
03796       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03797       goto out;
03798     }
03799   else if (result == DBUS_HANDLER_RESULT_HANDLED)
03800     {
03801       _dbus_verbose ("filter handled message in dispatch\n");
03802       goto out;
03803     }
03804 
03805   /* We're still protected from dispatch() reentrancy here
03806    * since we acquired the dispatcher
03807    */
03808   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
03809                  message,
03810                  dbus_message_get_type (message),
03811                  dbus_message_get_interface (message) ?
03812                  dbus_message_get_interface (message) :
03813                  "no interface",
03814                  dbus_message_get_member (message) ?
03815                  dbus_message_get_member (message) :
03816                  "no member",
03817                  dbus_message_get_signature (message));
03818 
03819   HAVE_LOCK_CHECK (connection);
03820   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03821                                                   message);
03822   
03823   CONNECTION_LOCK (connection);
03824 
03825   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03826     {
03827       _dbus_verbose ("object tree handled message in dispatch\n");
03828       goto out;
03829     }
03830 
03831   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03832     {
03833       DBusMessage *reply;
03834       DBusString str;
03835       DBusPreallocatedSend *preallocated;
03836 
03837       _dbus_verbose ("  sending error %s\n",
03838                      DBUS_ERROR_UNKNOWN_METHOD);
03839       
03840       if (!_dbus_string_init (&str))
03841         {
03842           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03843           _dbus_verbose ("no memory for error string in dispatch\n");
03844           goto out;
03845         }
03846               
03847       if (!_dbus_string_append_printf (&str,
03848                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03849                                        dbus_message_get_member (message),
03850                                        dbus_message_get_signature (message),
03851                                        dbus_message_get_interface (message)))
03852         {
03853           _dbus_string_free (&str);
03854           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03855           _dbus_verbose ("no memory for error string in dispatch\n");
03856           goto out;
03857         }
03858       
03859       reply = dbus_message_new_error (message,
03860                                       DBUS_ERROR_UNKNOWN_METHOD,
03861                                       _dbus_string_get_const_data (&str));
03862       _dbus_string_free (&str);
03863 
03864       if (reply == NULL)
03865         {
03866           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03867           _dbus_verbose ("no memory for error reply in dispatch\n");
03868           goto out;
03869         }
03870       
03871       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03872 
03873       if (preallocated == NULL)
03874         {
03875           dbus_message_unref (reply);
03876           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03877           _dbus_verbose ("no memory for error send in dispatch\n");
03878           goto out;
03879         }
03880 
03881       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03882                                                              reply, NULL);
03883 
03884       dbus_message_unref (reply);
03885       
03886       result = DBUS_HANDLER_RESULT_HANDLED;
03887     }
03888   
03889   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03890                  dbus_message_get_type (message),
03891                  dbus_message_get_interface (message) ?
03892                  dbus_message_get_interface (message) :
03893                  "no interface",
03894                  dbus_message_get_member (message) ?
03895                  dbus_message_get_member (message) :
03896                  "no member",
03897                  dbus_message_get_signature (message),
03898                  connection);
03899   
03900  out:
03901   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03902     {
03903       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03904       
03905       /* Put message back, and we'll start over.
03906        * Yes this means handlers must be idempotent if they
03907        * don't return HANDLED; c'est la vie.
03908        */
03909       _dbus_connection_putback_message_link_unlocked (connection,
03910                                                       message_link);
03911     }
03912   else
03913     {
03914       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03915       
03916       if (dbus_message_is_signal (message,
03917                                   DBUS_INTERFACE_LOCAL,
03918                                   "Disconnected"))
03919         {
03920           _dbus_bus_check_connection_and_unref_unlocked (connection);
03921 
03922           if (connection->exit_on_disconnect)
03923             {
03924               CONNECTION_UNLOCK (connection);            
03925  
03926               _dbus_verbose ("Exiting on Disconnected signal\n");
03927               _dbus_exit (1);
03928               _dbus_assert_not_reached ("Call to exit() returned");
03929             }
03930         }
03931       
03932       _dbus_list_free_link (message_link);
03933       dbus_message_unref (message); /* don't want the message to count in max message limits
03934                                      * in computing dispatch status below
03935                                      */
03936     }
03937   
03938   _dbus_connection_release_dispatch (connection);
03939   HAVE_LOCK_CHECK (connection);
03940 
03941   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03942   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03943 
03944   /* unlocks and calls user code */
03945   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03946   
03947   dbus_connection_unref (connection);
03948   
03949   return status;
03950 }
03951 
04010 dbus_bool_t
04011 dbus_connection_set_watch_functions (DBusConnection              *connection,
04012                                      DBusAddWatchFunction         add_function,
04013                                      DBusRemoveWatchFunction      remove_function,
04014                                      DBusWatchToggledFunction     toggled_function,
04015                                      void                        *data,
04016                                      DBusFreeFunction             free_data_function)
04017 {
04018   dbus_bool_t retval;
04019   DBusWatchList *watches;
04020 
04021   _dbus_return_val_if_fail (connection != NULL, FALSE);
04022   
04023   CONNECTION_LOCK (connection);
04024 
04025 #ifndef DBUS_DISABLE_CHECKS
04026   if (connection->watches == NULL)
04027     {
04028       _dbus_warn ("Re-entrant call to %s is not allowed\n",
04029                   _DBUS_FUNCTION_NAME);
04030       return FALSE;
04031     }
04032 #endif
04033   
04034   /* ref connection for slightly better reentrancy */
04035   _dbus_connection_ref_unlocked (connection);
04036 
04037   /* This can call back into user code, and we need to drop the
04038    * connection lock when it does. This is kind of a lame
04039    * way to do it.
04040    */
04041   watches = connection->watches;
04042   connection->watches = NULL;
04043   CONNECTION_UNLOCK (connection);
04044 
04045   retval = _dbus_watch_list_set_functions (watches,
04046                                            add_function, remove_function,
04047                                            toggled_function,
04048                                            data, free_data_function);
04049   CONNECTION_LOCK (connection);
04050   connection->watches = watches;
04051   
04052   CONNECTION_UNLOCK (connection);
04053   /* drop our paranoid refcount */
04054   dbus_connection_unref (connection);
04055   
04056   return retval;
04057 }
04058 
04092 dbus_bool_t
04093 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04094                                          DBusAddTimeoutFunction     add_function,
04095                                          DBusRemoveTimeoutFunction  remove_function,
04096                                          DBusTimeoutToggledFunction toggled_function,
04097                                          void                      *data,
04098                                          DBusFreeFunction           free_data_function)
04099 {
04100   dbus_bool_t retval;
04101   DBusTimeoutList *timeouts;
04102 
04103   _dbus_return_val_if_fail (connection != NULL, FALSE);
04104   
04105   CONNECTION_LOCK (connection);
04106 
04107 #ifndef DBUS_DISABLE_CHECKS
04108   if (connection->timeouts == NULL)
04109     {
04110       _dbus_warn ("Re-entrant call to %s is not allowed\n",
04111                   _DBUS_FUNCTION_NAME);
04112       return FALSE;
04113     }
04114 #endif
04115   
04116   /* ref connection for slightly better reentrancy */
04117   _dbus_connection_ref_unlocked (connection);
04118 
04119   timeouts = connection->timeouts;
04120   connection->timeouts = NULL;
04121   CONNECTION_UNLOCK (connection);
04122   
04123   retval = _dbus_timeout_list_set_functions (timeouts,
04124                                              add_function, remove_function,
04125                                              toggled_function,
04126                                              data, free_data_function);
04127   CONNECTION_LOCK (connection);
04128   connection->timeouts = timeouts;
04129   
04130   CONNECTION_UNLOCK (connection);
04131   /* drop our paranoid refcount */
04132   dbus_connection_unref (connection);
04133 
04134   return retval;
04135 }
04136 
04151 void
04152 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04153                                           DBusWakeupMainFunction     wakeup_main_function,
04154                                           void                      *data,
04155                                           DBusFreeFunction           free_data_function)
04156 {
04157   void *old_data;
04158   DBusFreeFunction old_free_data;
04159 
04160   _dbus_return_if_fail (connection != NULL);
04161   
04162   CONNECTION_LOCK (connection);
04163   old_data = connection->wakeup_main_data;
04164   old_free_data = connection->free_wakeup_main_data;
04165 
04166   connection->wakeup_main_function = wakeup_main_function;
04167   connection->wakeup_main_data = data;
04168   connection->free_wakeup_main_data = free_data_function;
04169   
04170   CONNECTION_UNLOCK (connection);
04171 
04172   /* Callback outside the lock */
04173   if (old_free_data)
04174     (*old_free_data) (old_data);
04175 }
04176 
04193 void
04194 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04195                                               DBusDispatchStatusFunction  function,
04196                                               void                       *data,
04197                                               DBusFreeFunction            free_data_function)
04198 {
04199   void *old_data;
04200   DBusFreeFunction old_free_data;
04201 
04202   _dbus_return_if_fail (connection != NULL);
04203   
04204   CONNECTION_LOCK (connection);
04205   old_data = connection->dispatch_status_data;
04206   old_free_data = connection->free_dispatch_status_data;
04207 
04208   connection->dispatch_status_function = function;
04209   connection->dispatch_status_data = data;
04210   connection->free_dispatch_status_data = free_data_function;
04211   
04212   CONNECTION_UNLOCK (connection);
04213 
04214   /* Callback outside the lock */
04215   if (old_free_data)
04216     (*old_free_data) (old_data);
04217 }
04218 
04231 dbus_bool_t
04232 dbus_connection_get_unix_fd (DBusConnection *connection,
04233                              int            *fd)
04234 {
04235   dbus_bool_t retval;
04236 
04237   _dbus_return_val_if_fail (connection != NULL, FALSE);
04238   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04239   
04240   CONNECTION_LOCK (connection);
04241   
04242   retval = _dbus_transport_get_unix_fd (connection->transport,
04243                                         fd);
04244 
04245   CONNECTION_UNLOCK (connection);
04246 
04247   return retval;
04248 }
04249 
04261 dbus_bool_t
04262 dbus_connection_get_unix_user (DBusConnection *connection,
04263                                unsigned long  *uid)
04264 {
04265   dbus_bool_t result;
04266 
04267   _dbus_return_val_if_fail (connection != NULL, FALSE);
04268   _dbus_return_val_if_fail (uid != NULL, FALSE);
04269   
04270   CONNECTION_LOCK (connection);
04271 
04272   if (!_dbus_transport_get_is_authenticated (connection->transport))
04273     result = FALSE;
04274   else
04275     result = _dbus_transport_get_unix_user (connection->transport,
04276                                             uid);
04277   CONNECTION_UNLOCK (connection);
04278 
04279   return result;
04280 }
04281 
04292 dbus_bool_t
04293 dbus_connection_get_unix_process_id (DBusConnection *connection,
04294                                      unsigned long  *pid)
04295 {
04296   dbus_bool_t result;
04297 
04298   _dbus_return_val_if_fail (connection != NULL, FALSE);
04299   _dbus_return_val_if_fail (pid != NULL, FALSE);
04300   
04301   CONNECTION_LOCK (connection);
04302 
04303   if (!_dbus_transport_get_is_authenticated (connection->transport))
04304     result = FALSE;
04305   else
04306     result = _dbus_transport_get_unix_process_id (connection->transport,
04307                                                   pid);
04308   CONNECTION_UNLOCK (connection);
04309 
04310   return result;
04311 }
04312 
04329 void
04330 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04331                                         DBusAllowUnixUserFunction   function,
04332                                         void                       *data,
04333                                         DBusFreeFunction            free_data_function)
04334 {
04335   void *old_data = NULL;
04336   DBusFreeFunction old_free_function = NULL;
04337 
04338   _dbus_return_if_fail (connection != NULL);
04339   
04340   CONNECTION_LOCK (connection);
04341   _dbus_transport_set_unix_user_function (connection->transport,
04342                                           function, data, free_data_function,
04343                                           &old_data, &old_free_function);
04344   CONNECTION_UNLOCK (connection);
04345 
04346   if (old_free_function != NULL)
04347     (* old_free_function) (old_data);    
04348 }
04349 
04371 dbus_bool_t
04372 dbus_connection_add_filter (DBusConnection            *connection,
04373                             DBusHandleMessageFunction  function,
04374                             void                      *user_data,
04375                             DBusFreeFunction           free_data_function)
04376 {
04377   DBusMessageFilter *filter;
04378   
04379   _dbus_return_val_if_fail (connection != NULL, FALSE);
04380   _dbus_return_val_if_fail (function != NULL, FALSE);
04381 
04382   filter = dbus_new0 (DBusMessageFilter, 1);
04383   if (filter == NULL)
04384     return FALSE;
04385 
04386   filter->refcount.value = 1;
04387   
04388   CONNECTION_LOCK (connection);
04389 
04390   if (!_dbus_list_append (&connection->filter_list,
04391                           filter))
04392     {
04393       _dbus_message_filter_unref (filter);
04394       CONNECTION_UNLOCK (connection);
04395       return FALSE;
04396     }
04397 
04398   /* Fill in filter after all memory allocated,
04399    * so we don't run the free_user_data_function
04400    * if the add_filter() fails
04401    */
04402   
04403   filter->function = function;
04404   filter->user_data = user_data;
04405   filter->free_user_data_function = free_data_function;
04406         
04407   CONNECTION_UNLOCK (connection);
04408   return TRUE;
04409 }
04410 
04423 void
04424 dbus_connection_remove_filter (DBusConnection            *connection,
04425                                DBusHandleMessageFunction  function,
04426                                void                      *user_data)
04427 {
04428   DBusList *link;
04429   DBusMessageFilter *filter;
04430   
04431   _dbus_return_if_fail (connection != NULL);
04432   _dbus_return_if_fail (function != NULL);
04433   
04434   CONNECTION_LOCK (connection);
04435 
04436   filter = NULL;
04437   
04438   link = _dbus_list_get_last_link (&connection->filter_list);
04439   while (link != NULL)
04440     {
04441       filter = link->data;
04442 
04443       if (filter->function == function &&
04444           filter->user_data == user_data)
04445         {
04446           _dbus_list_remove_link (&connection->filter_list, link);
04447           filter->function = NULL;
04448           
04449           break;
04450         }
04451         
04452       link = _dbus_list_get_prev_link (&connection->filter_list, link);
04453     }
04454   
04455   CONNECTION_UNLOCK (connection);
04456 
04457 #ifndef DBUS_DISABLE_CHECKS
04458   if (filter == NULL)
04459     {
04460       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04461                   function, user_data);
04462       return;
04463     }
04464 #endif
04465   
04466   /* Call application code */
04467   if (filter->free_user_data_function)
04468     (* filter->free_user_data_function) (filter->user_data);
04469 
04470   filter->free_user_data_function = NULL;
04471   filter->user_data = NULL;
04472   
04473   _dbus_message_filter_unref (filter);
04474 }
04475 
04487 dbus_bool_t
04488 dbus_connection_register_object_path (DBusConnection              *connection,
04489                                       const char                  *path,
04490                                       const DBusObjectPathVTable  *vtable,
04491                                       void                        *user_data)
04492 {
04493   char **decomposed_path;
04494   dbus_bool_t retval;
04495   
04496   _dbus_return_val_if_fail (connection != NULL, FALSE);
04497   _dbus_return_val_if_fail (path != NULL, FALSE);
04498   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04499   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04500 
04501   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04502     return FALSE;
04503 
04504   CONNECTION_LOCK (connection);
04505 
04506   retval = _dbus_object_tree_register (connection->objects,
04507                                        FALSE,
04508                                        (const char **) decomposed_path, vtable,
04509                                        user_data);
04510 
04511   CONNECTION_UNLOCK (connection);
04512 
04513   dbus_free_string_array (decomposed_path);
04514 
04515   return retval;
04516 }
04517 
04530 dbus_bool_t
04531 dbus_connection_register_fallback (DBusConnection              *connection,
04532                                    const char                  *path,
04533                                    const DBusObjectPathVTable  *vtable,
04534                                    void                        *user_data)
04535 {
04536   char **decomposed_path;
04537   dbus_bool_t retval;
04538   
04539   _dbus_return_val_if_fail (connection != NULL, FALSE);
04540   _dbus_return_val_if_fail (path != NULL, FALSE);
04541   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04542   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04543 
04544   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04545     return FALSE;
04546 
04547   CONNECTION_LOCK (connection);
04548 
04549   retval = _dbus_object_tree_register (connection->objects,
04550                                        TRUE,
04551                                        (const char **) decomposed_path, vtable,
04552                                        user_data);
04553 
04554   CONNECTION_UNLOCK (connection);
04555 
04556   dbus_free_string_array (decomposed_path);
04557 
04558   return retval;
04559 }
04560 
04570 dbus_bool_t
04571 dbus_connection_unregister_object_path (DBusConnection              *connection,
04572                                         const char                  *path)
04573 {
04574   char **decomposed_path;
04575 
04576   _dbus_return_val_if_fail (connection != NULL, FALSE);
04577   _dbus_return_val_if_fail (path != NULL, FALSE);
04578   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04579 
04580   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04581       return FALSE;
04582 
04583   CONNECTION_LOCK (connection);
04584 
04585   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04586 
04587   dbus_free_string_array (decomposed_path);
04588 
04589   return TRUE;
04590 }
04591 
04602 dbus_bool_t
04603 dbus_connection_get_object_path_data (DBusConnection *connection,
04604                                       const char     *path,
04605                                       void          **data_p)
04606 {
04607   char **decomposed_path;
04608 
04609   _dbus_return_val_if_fail (connection != NULL, FALSE);
04610   _dbus_return_val_if_fail (path != NULL, FALSE);
04611   _dbus_return_val_if_fail (data_p != NULL, FALSE);
04612 
04613   *data_p = NULL;
04614   
04615   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04616     return FALSE;
04617   
04618   CONNECTION_LOCK (connection);
04619 
04620   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04621 
04622   CONNECTION_UNLOCK (connection);
04623 
04624   dbus_free_string_array (decomposed_path);
04625 
04626   return TRUE;
04627 }
04628 
04639 dbus_bool_t
04640 dbus_connection_list_registered (DBusConnection              *connection,
04641                                  const char                  *parent_path,
04642                                  char                      ***child_entries)
04643 {
04644   char **decomposed_path;
04645   dbus_bool_t retval;
04646   _dbus_return_val_if_fail (connection != NULL, FALSE);
04647   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04648   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04649   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04650 
04651   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04652     return FALSE;
04653 
04654   CONNECTION_LOCK (connection);
04655 
04656   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04657                                                          (const char **) decomposed_path,
04658                                                          child_entries);
04659   dbus_free_string_array (decomposed_path);
04660 
04661   return retval;
04662 }
04663 
04664 static DBusDataSlotAllocator slot_allocator;
04665 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04666 
04681 dbus_bool_t
04682 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04683 {
04684   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04685                                           &_DBUS_LOCK_NAME (connection_slots),
04686                                           slot_p);
04687 }
04688 
04700 void
04701 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04702 {
04703   _dbus_return_if_fail (*slot_p >= 0);
04704   
04705   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04706 }
04707 
04721 dbus_bool_t
04722 dbus_connection_set_data (DBusConnection   *connection,
04723                           dbus_int32_t      slot,
04724                           void             *data,
04725                           DBusFreeFunction  free_data_func)
04726 {
04727   DBusFreeFunction old_free_func;
04728   void *old_data;
04729   dbus_bool_t retval;
04730 
04731   _dbus_return_val_if_fail (connection != NULL, FALSE);
04732   _dbus_return_val_if_fail (slot >= 0, FALSE);
04733   
04734   CONNECTION_LOCK (connection);
04735 
04736   retval = _dbus_data_slot_list_set (&slot_allocator,
04737                                      &connection->slot_list,
04738                                      slot, data, free_data_func,
04739                                      &old_free_func, &old_data);
04740   
04741   CONNECTION_UNLOCK (connection);
04742 
04743   if (retval)
04744     {
04745       /* Do the actual free outside the connection lock */
04746       if (old_free_func)
04747         (* old_free_func) (old_data);
04748     }
04749 
04750   return retval;
04751 }
04752 
04761 void*
04762 dbus_connection_get_data (DBusConnection   *connection,
04763                           dbus_int32_t      slot)
04764 {
04765   void *res;
04766 
04767   _dbus_return_val_if_fail (connection != NULL, NULL);
04768   
04769   CONNECTION_LOCK (connection);
04770 
04771   res = _dbus_data_slot_list_get (&slot_allocator,
04772                                   &connection->slot_list,
04773                                   slot);
04774   
04775   CONNECTION_UNLOCK (connection);
04776 
04777   return res;
04778 }
04779 
04786 void
04787 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04788 {  
04789   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04790 }
04791 
04800 void
04801 dbus_connection_set_max_message_size (DBusConnection *connection,
04802                                       long            size)
04803 {
04804   _dbus_return_if_fail (connection != NULL);
04805   
04806   CONNECTION_LOCK (connection);
04807   _dbus_transport_set_max_message_size (connection->transport,
04808                                         size);
04809   CONNECTION_UNLOCK (connection);
04810 }
04811 
04818 long
04819 dbus_connection_get_max_message_size (DBusConnection *connection)
04820 {
04821   long res;
04822 
04823   _dbus_return_val_if_fail (connection != NULL, 0);
04824   
04825   CONNECTION_LOCK (connection);
04826   res = _dbus_transport_get_max_message_size (connection->transport);
04827   CONNECTION_UNLOCK (connection);
04828   return res;
04829 }
04830 
04856 void
04857 dbus_connection_set_max_received_size (DBusConnection *connection,
04858                                        long            size)
04859 {
04860   _dbus_return_if_fail (connection != NULL);
04861   
04862   CONNECTION_LOCK (connection);
04863   _dbus_transport_set_max_received_size (connection->transport,
04864                                          size);
04865   CONNECTION_UNLOCK (connection);
04866 }
04867 
04874 long
04875 dbus_connection_get_max_received_size (DBusConnection *connection)
04876 {
04877   long res;
04878 
04879   _dbus_return_val_if_fail (connection != NULL, 0);
04880   
04881   CONNECTION_LOCK (connection);
04882   res = _dbus_transport_get_max_received_size (connection->transport);
04883   CONNECTION_UNLOCK (connection);
04884   return res;
04885 }
04886 
04897 long
04898 dbus_connection_get_outgoing_size (DBusConnection *connection)
04899 {
04900   long res;
04901 
04902   _dbus_return_val_if_fail (connection != NULL, 0);
04903   
04904   CONNECTION_LOCK (connection);
04905   res = _dbus_counter_get_value (connection->outgoing_counter);
04906   CONNECTION_UNLOCK (connection);
04907   return res;
04908 }
04909 

Generated on Fri Oct 20 11:46:23 2006 for D-Bus by  doxygen 1.4.7