• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002-2006  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-pending-call-internal.h"
00033 #include "dbus-list.h"
00034 #include "dbus-hash.h"
00035 #include "dbus-message-internal.h"
00036 #include "dbus-threads.h"
00037 #include "dbus-protocol.h"
00038 #include "dbus-dataslot.h"
00039 #include "dbus-string.h"
00040 #include "dbus-pending-call.h"
00041 #include "dbus-object-tree.h"
00042 #include "dbus-threads-internal.h"
00043 #include "dbus-bus.h"
00044 
00045 #ifdef DBUS_DISABLE_CHECKS
00046 #define TOOK_LOCK_CHECK(connection)
00047 #define RELEASING_LOCK_CHECK(connection)
00048 #define HAVE_LOCK_CHECK(connection)
00049 #else
00050 #define TOOK_LOCK_CHECK(connection) do {                \
00051     _dbus_assert (!(connection)->have_connection_lock); \
00052     (connection)->have_connection_lock = TRUE;          \
00053   } while (0)
00054 #define RELEASING_LOCK_CHECK(connection) do {            \
00055     _dbus_assert ((connection)->have_connection_lock);   \
00056     (connection)->have_connection_lock = FALSE;          \
00057   } while (0)
00058 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00059 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00060 #endif
00061 
00062 #define TRACE_LOCKS 1
00063 
00064 #define CONNECTION_LOCK(connection)   do {                                      \
00065     if (TRACE_LOCKS) { _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME); }   \
00066     _dbus_mutex_lock ((connection)->mutex);                                      \
00067     TOOK_LOCK_CHECK (connection);                                               \
00068   } while (0)
00069 
00070 #define CONNECTION_UNLOCK(connection) do {                                              \
00071     if (TRACE_LOCKS) { _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);  }        \
00072     RELEASING_LOCK_CHECK (connection);                                                  \
00073     _dbus_mutex_unlock ((connection)->mutex);                                            \
00074   } while (0)
00075 
00076 #define DISPATCH_STATUS_NAME(s)                                            \
00077                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00078                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00079                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00080                       "???")
00081 
00202 typedef struct DBusMessageFilter DBusMessageFilter;
00203 
00207 struct DBusMessageFilter
00208 {
00209   DBusAtomic refcount; 
00210   DBusHandleMessageFunction function; 
00211   void *user_data; 
00212   DBusFreeFunction free_user_data_function; 
00213 };
00214 
00215 
00219 struct DBusPreallocatedSend
00220 {
00221   DBusConnection *connection; 
00222   DBusList *queue_link;       
00223   DBusList *counter_link;     
00224 };
00225 
00226 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00227 
00231 struct DBusConnection
00232 {
00233   DBusAtomic refcount; 
00235   DBusMutex *mutex; 
00237   DBusMutex *dispatch_mutex;     
00238   DBusCondVar *dispatch_cond;    
00239   DBusMutex *io_path_mutex;      
00240   DBusCondVar *io_path_cond;     
00242   DBusList *outgoing_messages; 
00243   DBusList *incoming_messages; 
00245   DBusMessage *message_borrowed; 
00249   int n_outgoing;              
00250   int n_incoming;              
00252   DBusCounter *outgoing_counter; 
00254   DBusTransport *transport;    
00255   DBusWatchList *watches;      
00256   DBusTimeoutList *timeouts;   
00258   DBusList *filter_list;        
00260   DBusDataSlotList slot_list;   
00262   DBusHashTable *pending_replies;  
00264   dbus_uint32_t client_serial;       
00265   DBusList *disconnect_message_link; 
00267   DBusWakeupMainFunction wakeup_main_function; 
00268   void *wakeup_main_data; 
00269   DBusFreeFunction free_wakeup_main_data; 
00271   DBusDispatchStatusFunction dispatch_status_function; 
00272   void *dispatch_status_data; 
00273   DBusFreeFunction free_dispatch_status_data; 
00275   DBusDispatchStatus last_dispatch_status; 
00277   DBusList *link_cache; 
00280   DBusObjectTree *objects; 
00282   char *server_guid; 
00284   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00285    * from connection->mutex and all bitfields in a word have to be read/written together.
00286    * So you can't have a different lock for different bitfields in the same word.
00287    */
00288   dbus_bool_t dispatch_acquired; 
00289   dbus_bool_t io_path_acquired;  
00291   unsigned int shareable : 1; 
00293   unsigned int exit_on_disconnect : 1; 
00295   unsigned int route_peer_messages : 1; 
00297   unsigned int disconnected_message_arrived : 1;   
00301   unsigned int disconnected_message_processed : 1; 
00305 #ifndef DBUS_DISABLE_CHECKS
00306   unsigned int have_connection_lock : 1; 
00307 #endif
00308   
00309 #ifndef DBUS_DISABLE_CHECKS
00310   int generation; 
00311 #endif 
00312 };
00313 
00314 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00315 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00316                                                                               DBusDispatchStatus  new_status);
00317 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00318 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00319 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00320 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00321 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00322 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00323 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
00324                                                                               dbus_uint32_t       client_serial);
00325 
00326 static DBusMessageFilter *
00327 _dbus_message_filter_ref (DBusMessageFilter *filter)
00328 {
00329   _dbus_assert (filter->refcount.value > 0);
00330   _dbus_atomic_inc (&filter->refcount);
00331 
00332   return filter;
00333 }
00334 
00335 static void
00336 _dbus_message_filter_unref (DBusMessageFilter *filter)
00337 {
00338   _dbus_assert (filter->refcount.value > 0);
00339 
00340   if (_dbus_atomic_dec (&filter->refcount) == 1)
00341     {
00342       if (filter->free_user_data_function)
00343         (* filter->free_user_data_function) (filter->user_data);
00344       
00345       dbus_free (filter);
00346     }
00347 }
00348 
00354 void
00355 _dbus_connection_lock (DBusConnection *connection)
00356 {
00357   CONNECTION_LOCK (connection);
00358 }
00359 
00365 void
00366 _dbus_connection_unlock (DBusConnection *connection)
00367 {
00368   CONNECTION_UNLOCK (connection);
00369 }
00370 
00378 static void
00379 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00380 {
00381   if (connection->wakeup_main_function)
00382     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00383 }
00384 
00385 #ifdef DBUS_BUILD_TESTS
00386 /* For now this function isn't used */
00396 dbus_bool_t
00397 _dbus_connection_queue_received_message (DBusConnection *connection,
00398                                          DBusMessage    *message)
00399 {
00400   DBusList *link;
00401 
00402   link = _dbus_list_alloc_link (message);
00403   if (link == NULL)
00404     return FALSE;
00405 
00406   dbus_message_ref (message);
00407   _dbus_connection_queue_received_message_link (connection, link);
00408 
00409   return TRUE;
00410 }
00411 
00424 void 
00425 _dbus_connection_test_get_locks (DBusConnection *connection,
00426                                  DBusMutex     **mutex_loc,
00427                                  DBusMutex     **dispatch_mutex_loc,
00428                                  DBusMutex     **io_path_mutex_loc,
00429                                  DBusCondVar   **dispatch_cond_loc,
00430                                  DBusCondVar   **io_path_cond_loc)
00431 {
00432   *mutex_loc = connection->mutex;
00433   *dispatch_mutex_loc = connection->dispatch_mutex;
00434   *io_path_mutex_loc = connection->io_path_mutex; 
00435   *dispatch_cond_loc = connection->dispatch_cond;
00436   *io_path_cond_loc = connection->io_path_cond;
00437 }
00438 #endif
00439 
00448 void
00449 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00450                                               DBusList        *link)
00451 {
00452   DBusPendingCall *pending;
00453   dbus_uint32_t reply_serial;
00454   DBusMessage *message;
00455   
00456   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00457   
00458   _dbus_list_append_link (&connection->incoming_messages,
00459                           link);
00460   message = link->data;
00461 
00462   /* If this is a reply we're waiting on, remove timeout for it */
00463   reply_serial = dbus_message_get_reply_serial (message);
00464   if (reply_serial != 0)
00465     {
00466       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00467                                              reply_serial);
00468       if (pending != NULL)
00469         {
00470           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00471             _dbus_connection_remove_timeout_unlocked (connection,
00472                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00473 
00474           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00475         }
00476     }
00477   
00478   
00479 
00480   connection->n_incoming += 1;
00481 
00482   _dbus_connection_wakeup_mainloop (connection);
00483   
00484   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00485                  message,
00486                  dbus_message_get_type (message),
00487                  dbus_message_get_path (message) ?
00488                  dbus_message_get_path (message) :
00489                  "no path",
00490                  dbus_message_get_interface (message) ?
00491                  dbus_message_get_interface (message) :
00492                  "no interface",
00493                  dbus_message_get_member (message) ?
00494                  dbus_message_get_member (message) :
00495                  "no member",
00496                  dbus_message_get_signature (message),
00497                  dbus_message_get_reply_serial (message),
00498                  connection,
00499                  connection->n_incoming);}
00500 
00509 void
00510 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00511                                                  DBusList *link)
00512 {
00513   HAVE_LOCK_CHECK (connection);
00514   
00515   _dbus_list_append_link (&connection->incoming_messages, link);
00516 
00517   connection->n_incoming += 1;
00518 
00519   _dbus_connection_wakeup_mainloop (connection);
00520   
00521   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00522                  link->data, connection, connection->n_incoming);
00523 }
00524 
00525 
00533 dbus_bool_t
00534 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00535 {
00536   HAVE_LOCK_CHECK (connection);
00537   return connection->outgoing_messages != NULL;
00538 }
00539 
00549 dbus_bool_t
00550 dbus_connection_has_messages_to_send (DBusConnection *connection)
00551 {
00552   dbus_bool_t v;
00553   
00554   _dbus_return_val_if_fail (connection != NULL, FALSE);
00555 
00556   CONNECTION_LOCK (connection);
00557   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00558   CONNECTION_UNLOCK (connection);
00559 
00560   return v;
00561 }
00562 
00570 DBusMessage*
00571 _dbus_connection_get_message_to_send (DBusConnection *connection)
00572 {
00573   HAVE_LOCK_CHECK (connection);
00574   
00575   return _dbus_list_get_last (&connection->outgoing_messages);
00576 }
00577 
00586 void
00587 _dbus_connection_message_sent (DBusConnection *connection,
00588                                DBusMessage    *message)
00589 {
00590   DBusList *link;
00591 
00592   HAVE_LOCK_CHECK (connection);
00593   
00594   /* This can be called before we even complete authentication, since
00595    * it's called on disconnect to clean up the outgoing queue.
00596    * It's also called as we successfully send each message.
00597    */
00598   
00599   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00600   _dbus_assert (link != NULL);
00601   _dbus_assert (link->data == message);
00602 
00603   /* Save this link in the link cache */
00604   _dbus_list_unlink (&connection->outgoing_messages,
00605                      link);
00606   _dbus_list_prepend_link (&connection->link_cache, link);
00607   
00608   connection->n_outgoing -= 1;
00609 
00610   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00611                  message,
00612                  dbus_message_get_type (message),
00613                  dbus_message_get_path (message) ?
00614                  dbus_message_get_path (message) :
00615                  "no path",
00616                  dbus_message_get_interface (message) ?
00617                  dbus_message_get_interface (message) :
00618                  "no interface",
00619                  dbus_message_get_member (message) ?
00620                  dbus_message_get_member (message) :
00621                  "no member",
00622                  dbus_message_get_signature (message),
00623                  connection, connection->n_outgoing);
00624 
00625   /* Save this link in the link cache also */
00626   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00627                                      &link);
00628   _dbus_list_prepend_link (&connection->link_cache, link);
00629   
00630   dbus_message_unref (message);
00631 }
00632 
00634 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00635                                                   DBusWatch     *watch);
00637 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00638                                                   DBusWatch     *watch);
00640 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00641                                                   DBusWatch     *watch,
00642                                                   dbus_bool_t    enabled);
00643 
00644 static dbus_bool_t
00645 protected_change_watch (DBusConnection         *connection,
00646                         DBusWatch              *watch,
00647                         DBusWatchAddFunction    add_function,
00648                         DBusWatchRemoveFunction remove_function,
00649                         DBusWatchToggleFunction toggle_function,
00650                         dbus_bool_t             enabled)
00651 {
00652   DBusWatchList *watches;
00653   dbus_bool_t retval;
00654   
00655   HAVE_LOCK_CHECK (connection);
00656 
00657   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00658    * drop lock and call out" one; but it has to be propagated up through all callers
00659    */
00660   
00661   watches = connection->watches;
00662   if (watches)
00663     {
00664       connection->watches = NULL;
00665       _dbus_connection_ref_unlocked (connection);
00666       CONNECTION_UNLOCK (connection);
00667 
00668       if (add_function)
00669         retval = (* add_function) (watches, watch);
00670       else if (remove_function)
00671         {
00672           retval = TRUE;
00673           (* remove_function) (watches, watch);
00674         }
00675       else
00676         {
00677           retval = TRUE;
00678           (* toggle_function) (watches, watch, enabled);
00679         }
00680       
00681       CONNECTION_LOCK (connection);
00682       connection->watches = watches;
00683       _dbus_connection_unref_unlocked (connection);
00684 
00685       return retval;
00686     }
00687   else
00688     return FALSE;
00689 }
00690      
00691 
00703 dbus_bool_t
00704 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00705                                      DBusWatch      *watch)
00706 {
00707   return protected_change_watch (connection, watch,
00708                                  _dbus_watch_list_add_watch,
00709                                  NULL, NULL, FALSE);
00710 }
00711 
00721 void
00722 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00723                                         DBusWatch      *watch)
00724 {
00725   protected_change_watch (connection, watch,
00726                           NULL,
00727                           _dbus_watch_list_remove_watch,
00728                           NULL, FALSE);
00729 }
00730 
00741 void
00742 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00743                                         DBusWatch      *watch,
00744                                         dbus_bool_t     enabled)
00745 {
00746   _dbus_assert (watch != NULL);
00747 
00748   protected_change_watch (connection, watch,
00749                           NULL, NULL,
00750                           _dbus_watch_list_toggle_watch,
00751                           enabled);
00752 }
00753 
00755 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00756                                                    DBusTimeout     *timeout);
00758 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00759                                                    DBusTimeout     *timeout);
00761 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00762                                                    DBusTimeout     *timeout,
00763                                                    dbus_bool_t      enabled);
00764 
00765 static dbus_bool_t
00766 protected_change_timeout (DBusConnection           *connection,
00767                           DBusTimeout              *timeout,
00768                           DBusTimeoutAddFunction    add_function,
00769                           DBusTimeoutRemoveFunction remove_function,
00770                           DBusTimeoutToggleFunction toggle_function,
00771                           dbus_bool_t               enabled)
00772 {
00773   DBusTimeoutList *timeouts;
00774   dbus_bool_t retval;
00775   
00776   HAVE_LOCK_CHECK (connection);
00777 
00778   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00779    * drop lock and call out" one; but it has to be propagated up through all callers
00780    */
00781   
00782   timeouts = connection->timeouts;
00783   if (timeouts)
00784     {
00785       connection->timeouts = NULL;
00786       _dbus_connection_ref_unlocked (connection);
00787       CONNECTION_UNLOCK (connection);
00788 
00789       if (add_function)
00790         retval = (* add_function) (timeouts, timeout);
00791       else if (remove_function)
00792         {
00793           retval = TRUE;
00794           (* remove_function) (timeouts, timeout);
00795         }
00796       else
00797         {
00798           retval = TRUE;
00799           (* toggle_function) (timeouts, timeout, enabled);
00800         }
00801       
00802       CONNECTION_LOCK (connection);
00803       connection->timeouts = timeouts;
00804       _dbus_connection_unref_unlocked (connection);
00805 
00806       return retval;
00807     }
00808   else
00809     return FALSE;
00810 }
00811 
00824 dbus_bool_t
00825 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00826                                        DBusTimeout    *timeout)
00827 {
00828   return protected_change_timeout (connection, timeout,
00829                                    _dbus_timeout_list_add_timeout,
00830                                    NULL, NULL, FALSE);
00831 }
00832 
00842 void
00843 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00844                                           DBusTimeout    *timeout)
00845 {
00846   protected_change_timeout (connection, timeout,
00847                             NULL,
00848                             _dbus_timeout_list_remove_timeout,
00849                             NULL, FALSE);
00850 }
00851 
00862 void
00863 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00864                                           DBusTimeout      *timeout,
00865                                           dbus_bool_t       enabled)
00866 {
00867   protected_change_timeout (connection, timeout,
00868                             NULL, NULL,
00869                             _dbus_timeout_list_toggle_timeout,
00870                             enabled);
00871 }
00872 
00873 static dbus_bool_t
00874 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00875                                                DBusPendingCall *pending)
00876 {
00877   dbus_uint32_t reply_serial;
00878   DBusTimeout *timeout;
00879 
00880   HAVE_LOCK_CHECK (connection);
00881 
00882   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00883 
00884   _dbus_assert (reply_serial != 0);
00885 
00886   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00887 
00888   if (timeout)
00889     {
00890       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00891         return FALSE;
00892       
00893       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00894                                         reply_serial,
00895                                         pending))
00896         {
00897           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00898 
00899           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00900           HAVE_LOCK_CHECK (connection);
00901           return FALSE;
00902         }
00903       
00904       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00905     }
00906   else
00907     {
00908       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00909                                         reply_serial,
00910                                         pending))
00911         {
00912           HAVE_LOCK_CHECK (connection);
00913           return FALSE;
00914         }
00915     }
00916 
00917   _dbus_pending_call_ref_unlocked (pending);
00918 
00919   HAVE_LOCK_CHECK (connection);
00920   
00921   return TRUE;
00922 }
00923 
00924 static void
00925 free_pending_call_on_hash_removal (void *data)
00926 {
00927   DBusPendingCall *pending;
00928   DBusConnection  *connection;
00929   
00930   if (data == NULL)
00931     return;
00932 
00933   pending = data;
00934 
00935   connection = _dbus_pending_call_get_connection_unlocked (pending);
00936 
00937   HAVE_LOCK_CHECK (connection);
00938   
00939   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00940     {
00941       _dbus_connection_remove_timeout_unlocked (connection,
00942                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00943       
00944       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00945     }
00946 
00947   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00948    * here, but the pending call finalizer could in principle call out to 
00949    * application code so we pretty much have to... some larger code reorg 
00950    * might be needed.
00951    */
00952   _dbus_connection_ref_unlocked (connection);
00953   _dbus_pending_call_unref_and_unlock (pending);
00954   CONNECTION_LOCK (connection);
00955   _dbus_connection_unref_unlocked (connection);
00956 }
00957 
00958 static void
00959 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00960                                                DBusPendingCall *pending)
00961 {
00962   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00963    * say the least.
00964    */
00965   _dbus_hash_table_remove_int (connection->pending_replies,
00966                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00967 }
00968 
00969 static void
00970 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00971                                                  DBusPendingCall *pending)
00972 {
00973   /* The idea here is to avoid finalizing the pending call
00974    * with the lock held, since there's a destroy notifier
00975    * in pending call that goes out to application code.
00976    *
00977    * There's an extra unlock inside the hash table
00978    * "free pending call" function FIXME...
00979    */
00980   _dbus_pending_call_ref_unlocked (pending);
00981   _dbus_hash_table_remove_int (connection->pending_replies,
00982                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00983 
00984   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00985       _dbus_connection_remove_timeout_unlocked (connection,
00986               _dbus_pending_call_get_timeout_unlocked (pending));
00987 
00988   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00989 
00990   _dbus_pending_call_unref_and_unlock (pending);
00991 }
00992 
01001 void
01002 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01003                                       DBusPendingCall *pending)
01004 {
01005   CONNECTION_LOCK (connection);
01006   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01007 }
01008 
01018 static dbus_bool_t
01019 _dbus_connection_acquire_io_path (DBusConnection *connection,
01020                                   int             timeout_milliseconds)
01021 {
01022   dbus_bool_t we_acquired;
01023   
01024   HAVE_LOCK_CHECK (connection);
01025 
01026   /* We don't want the connection to vanish */
01027   _dbus_connection_ref_unlocked (connection);
01028 
01029   /* We will only touch io_path_acquired which is protected by our mutex */
01030   CONNECTION_UNLOCK (connection);
01031   
01032   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01033   _dbus_mutex_lock (connection->io_path_mutex);
01034 
01035   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01036                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01037 
01038   we_acquired = FALSE;
01039   
01040   if (connection->io_path_acquired)
01041     {
01042       if (timeout_milliseconds != -1)
01043         {
01044           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01045                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
01046 
01047           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01048                                            connection->io_path_mutex,
01049                                            timeout_milliseconds))
01050             {
01051               /* We timed out before anyone signaled. */
01052               /* (writing the loop to handle the !timedout case by
01053                * waiting longer if needed is a pain since dbus
01054                * wraps pthread_cond_timedwait to take a relative
01055                * time instead of absolute, something kind of stupid
01056                * on our part. for now it doesn't matter, we will just
01057                * end up back here eventually.)
01058                */
01059             }
01060         }
01061       else
01062         {
01063           while (connection->io_path_acquired)
01064             {
01065               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01066               _dbus_condvar_wait (connection->io_path_cond, 
01067                                   connection->io_path_mutex);
01068             }
01069         }
01070     }
01071   
01072   if (!connection->io_path_acquired)
01073     {
01074       we_acquired = TRUE;
01075       connection->io_path_acquired = TRUE;
01076     }
01077   
01078   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01079                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01080 
01081   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01082   _dbus_mutex_unlock (connection->io_path_mutex);
01083 
01084   CONNECTION_LOCK (connection);
01085   
01086   HAVE_LOCK_CHECK (connection);
01087 
01088   _dbus_connection_unref_unlocked (connection);
01089   
01090   return we_acquired;
01091 }
01092 
01100 static void
01101 _dbus_connection_release_io_path (DBusConnection *connection)
01102 {
01103   HAVE_LOCK_CHECK (connection);
01104   
01105   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01106   _dbus_mutex_lock (connection->io_path_mutex);
01107   
01108   _dbus_assert (connection->io_path_acquired);
01109 
01110   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01111                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01112   
01113   connection->io_path_acquired = FALSE;
01114   _dbus_condvar_wake_one (connection->io_path_cond);
01115 
01116   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01117   _dbus_mutex_unlock (connection->io_path_mutex);
01118 }
01119 
01155 void
01156 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01157                                         DBusPendingCall *pending,
01158                                         unsigned int    flags,
01159                                         int             timeout_milliseconds)
01160 {
01161   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01162   
01163   HAVE_LOCK_CHECK (connection);
01164   
01165   if (connection->n_outgoing == 0)
01166     flags &= ~DBUS_ITERATION_DO_WRITING;
01167 
01168   if (_dbus_connection_acquire_io_path (connection,
01169                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01170     {
01171       HAVE_LOCK_CHECK (connection);
01172       
01173       if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01174         {
01175           _dbus_verbose ("pending call completed while acquiring I/O path");
01176         }
01177       else if ( (pending != NULL) &&
01178                 _dbus_connection_peek_for_reply_unlocked (connection,
01179                                                           _dbus_pending_call_get_reply_serial_unlocked (pending)))
01180         {
01181           _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01182         }
01183       else
01184         {
01185           _dbus_transport_do_iteration (connection->transport,
01186                                         flags, timeout_milliseconds);
01187         }
01188 
01189       _dbus_connection_release_io_path (connection);
01190     }
01191 
01192   HAVE_LOCK_CHECK (connection);
01193 
01194   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01195 }
01196 
01206 DBusConnection*
01207 _dbus_connection_new_for_transport (DBusTransport *transport)
01208 {
01209   DBusConnection *connection;
01210   DBusWatchList *watch_list;
01211   DBusTimeoutList *timeout_list;
01212   DBusHashTable *pending_replies;
01213   DBusList *disconnect_link;
01214   DBusMessage *disconnect_message;
01215   DBusCounter *outgoing_counter;
01216   DBusObjectTree *objects;
01217   
01218   watch_list = NULL;
01219   connection = NULL;
01220   pending_replies = NULL;
01221   timeout_list = NULL;
01222   disconnect_link = NULL;
01223   disconnect_message = NULL;
01224   outgoing_counter = NULL;
01225   objects = NULL;
01226   
01227   watch_list = _dbus_watch_list_new ();
01228   if (watch_list == NULL)
01229     goto error;
01230 
01231   timeout_list = _dbus_timeout_list_new ();
01232   if (timeout_list == NULL)
01233     goto error;  
01234 
01235   pending_replies =
01236     _dbus_hash_table_new (DBUS_HASH_INT,
01237                           NULL,
01238                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01239   if (pending_replies == NULL)
01240     goto error;
01241   
01242   connection = dbus_new0 (DBusConnection, 1);
01243   if (connection == NULL)
01244     goto error;
01245 
01246   _dbus_mutex_new_at_location (&connection->mutex);
01247   if (connection->mutex == NULL)
01248     goto error;
01249 
01250   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01251   if (connection->io_path_mutex == NULL)
01252     goto error;
01253 
01254   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01255   if (connection->dispatch_mutex == NULL)
01256     goto error;
01257   
01258   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01259   if (connection->dispatch_cond == NULL)
01260     goto error;
01261   
01262   _dbus_condvar_new_at_location (&connection->io_path_cond);
01263   if (connection->io_path_cond == NULL)
01264     goto error;
01265 
01266   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01267                                                 DBUS_INTERFACE_LOCAL,
01268                                                 "Disconnected");
01269   
01270   if (disconnect_message == NULL)
01271     goto error;
01272 
01273   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01274   if (disconnect_link == NULL)
01275     goto error;
01276 
01277   outgoing_counter = _dbus_counter_new ();
01278   if (outgoing_counter == NULL)
01279     goto error;
01280 
01281   objects = _dbus_object_tree_new (connection);
01282   if (objects == NULL)
01283     goto error;
01284   
01285   if (_dbus_modify_sigpipe)
01286     _dbus_disable_sigpipe ();
01287   
01288   connection->refcount.value = 1;
01289   connection->transport = transport;
01290   connection->watches = watch_list;
01291   connection->timeouts = timeout_list;
01292   connection->pending_replies = pending_replies;
01293   connection->outgoing_counter = outgoing_counter;
01294   connection->filter_list = NULL;
01295   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01296   connection->objects = objects;
01297   connection->exit_on_disconnect = FALSE;
01298   connection->shareable = FALSE;
01299   connection->route_peer_messages = FALSE;
01300   connection->disconnected_message_arrived = FALSE;
01301   connection->disconnected_message_processed = FALSE;
01302   
01303 #ifndef DBUS_DISABLE_CHECKS
01304   connection->generation = _dbus_current_generation;
01305 #endif
01306   
01307   _dbus_data_slot_list_init (&connection->slot_list);
01308 
01309   connection->client_serial = 1;
01310 
01311   connection->disconnect_message_link = disconnect_link;
01312 
01313   CONNECTION_LOCK (connection);
01314   
01315   if (!_dbus_transport_set_connection (transport, connection))
01316     {
01317       CONNECTION_UNLOCK (connection);
01318 
01319       goto error;
01320     }
01321 
01322   _dbus_transport_ref (transport);
01323 
01324   CONNECTION_UNLOCK (connection);
01325   
01326   return connection;
01327   
01328  error:
01329   if (disconnect_message != NULL)
01330     dbus_message_unref (disconnect_message);
01331   
01332   if (disconnect_link != NULL)
01333     _dbus_list_free_link (disconnect_link);
01334   
01335   if (connection != NULL)
01336     {
01337       _dbus_condvar_free_at_location (&connection->io_path_cond);
01338       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01339       _dbus_mutex_free_at_location (&connection->mutex);
01340       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01341       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01342       dbus_free (connection);
01343     }
01344   if (pending_replies)
01345     _dbus_hash_table_unref (pending_replies);
01346   
01347   if (watch_list)
01348     _dbus_watch_list_free (watch_list);
01349 
01350   if (timeout_list)
01351     _dbus_timeout_list_free (timeout_list);
01352 
01353   if (outgoing_counter)
01354     _dbus_counter_unref (outgoing_counter);
01355 
01356   if (objects)
01357     _dbus_object_tree_unref (objects);
01358   
01359   return NULL;
01360 }
01361 
01369 DBusConnection *
01370 _dbus_connection_ref_unlocked (DBusConnection *connection)
01371 {  
01372   _dbus_assert (connection != NULL);
01373   _dbus_assert (connection->generation == _dbus_current_generation);
01374 
01375   HAVE_LOCK_CHECK (connection);
01376   
01377 #ifdef DBUS_HAVE_ATOMIC_INT
01378   _dbus_atomic_inc (&connection->refcount);
01379 #else
01380   _dbus_assert (connection->refcount.value > 0);
01381   connection->refcount.value += 1;
01382 #endif
01383 
01384   return connection;
01385 }
01386 
01393 void
01394 _dbus_connection_unref_unlocked (DBusConnection *connection)
01395 {
01396   dbus_bool_t last_unref;
01397 
01398   HAVE_LOCK_CHECK (connection);
01399   
01400   _dbus_assert (connection != NULL);
01401 
01402   /* The connection lock is better than the global
01403    * lock in the atomic increment fallback
01404    */
01405   
01406 #ifdef DBUS_HAVE_ATOMIC_INT
01407   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01408 #else
01409   _dbus_assert (connection->refcount.value > 0);
01410 
01411   connection->refcount.value -= 1;
01412   last_unref = (connection->refcount.value == 0);  
01413 #if 0
01414   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01415 #endif
01416 #endif
01417   
01418   if (last_unref)
01419     _dbus_connection_last_unref (connection);
01420 }
01421 
01422 static dbus_uint32_t
01423 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01424 {
01425   dbus_uint32_t serial;
01426 
01427   serial = connection->client_serial++;
01428 
01429   if (connection->client_serial == 0)
01430     connection->client_serial = 1;
01431 
01432   return serial;
01433 }
01434 
01448 dbus_bool_t
01449 _dbus_connection_handle_watch (DBusWatch                   *watch,
01450                                unsigned int                 condition,
01451                                void                        *data)
01452 {
01453   DBusConnection *connection;
01454   dbus_bool_t retval;
01455   DBusDispatchStatus status;
01456 
01457   connection = data;
01458 
01459   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01460   
01461   CONNECTION_LOCK (connection);
01462 
01463   if (!_dbus_connection_acquire_io_path (connection, 1))
01464     {
01465       /* another thread is handling the message */
01466       CONNECTION_UNLOCK (connection);
01467       return TRUE;
01468     }
01469 
01470   HAVE_LOCK_CHECK (connection);
01471   retval = _dbus_transport_handle_watch (connection->transport,
01472                                          watch, condition);
01473 
01474   _dbus_connection_release_io_path (connection);
01475 
01476   HAVE_LOCK_CHECK (connection);
01477 
01478   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01479   
01480   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01481 
01482   /* this calls out to user code */
01483   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01484 
01485   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01486   
01487   return retval;
01488 }
01489 
01490 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01491 static DBusHashTable *shared_connections = NULL;
01492 static DBusList *shared_connections_no_guid = NULL;
01493 
01494 static void
01495 close_connection_on_shutdown (DBusConnection *connection)
01496 {
01497   DBusMessage *message;
01498 
01499   dbus_connection_ref (connection);
01500   _dbus_connection_close_possibly_shared (connection);
01501 
01502   /* Churn through to the Disconnected message */
01503   while ((message = dbus_connection_pop_message (connection)))
01504     {
01505       dbus_message_unref (message);
01506     }
01507   dbus_connection_unref (connection);
01508 }
01509 
01510 static void
01511 shared_connections_shutdown (void *data)
01512 {
01513   int n_entries;
01514   
01515   _DBUS_LOCK (shared_connections);
01516   
01517   /* This is a little bit unpleasant... better ideas? */
01518   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01519     {
01520       DBusConnection *connection;
01521       DBusHashIter iter;
01522       
01523       _dbus_hash_iter_init (shared_connections, &iter);
01524       _dbus_hash_iter_next (&iter);
01525        
01526       connection = _dbus_hash_iter_get_value (&iter);
01527 
01528       _DBUS_UNLOCK (shared_connections);
01529       close_connection_on_shutdown (connection);
01530       _DBUS_LOCK (shared_connections);
01531 
01532       /* The connection should now be dead and not in our hash ... */
01533       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01534     }
01535 
01536   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01537   
01538   _dbus_hash_table_unref (shared_connections);
01539   shared_connections = NULL;
01540 
01541   if (shared_connections_no_guid != NULL)
01542     {
01543       DBusConnection *connection;
01544       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01545       while (connection != NULL)
01546         {
01547           _DBUS_UNLOCK (shared_connections);
01548           close_connection_on_shutdown (connection);
01549           _DBUS_LOCK (shared_connections);
01550           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01551         }
01552     }
01553 
01554   shared_connections_no_guid = NULL;
01555   
01556   _DBUS_UNLOCK (shared_connections);
01557 }
01558 
01559 static dbus_bool_t
01560 connection_lookup_shared (DBusAddressEntry  *entry,
01561                           DBusConnection   **result)
01562 {
01563   _dbus_verbose ("checking for existing connection\n");
01564   
01565   *result = NULL;
01566   
01567   _DBUS_LOCK (shared_connections);
01568 
01569   if (shared_connections == NULL)
01570     {
01571       _dbus_verbose ("creating shared_connections hash table\n");
01572       
01573       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01574                                                  dbus_free,
01575                                                  NULL);
01576       if (shared_connections == NULL)
01577         {
01578           _DBUS_UNLOCK (shared_connections);
01579           return FALSE;
01580         }
01581 
01582       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01583         {
01584           _dbus_hash_table_unref (shared_connections);
01585           shared_connections = NULL;
01586           _DBUS_UNLOCK (shared_connections);
01587           return FALSE;
01588         }
01589 
01590       _dbus_verbose ("  successfully created shared_connections\n");
01591       
01592       _DBUS_UNLOCK (shared_connections);
01593       return TRUE; /* no point looking up in the hash we just made */
01594     }
01595   else
01596     {
01597       const char *guid;
01598 
01599       guid = dbus_address_entry_get_value (entry, "guid");
01600       
01601       if (guid != NULL)
01602         {
01603           DBusConnection *connection;
01604           
01605           connection = _dbus_hash_table_lookup_string (shared_connections,
01606                                                        guid);
01607 
01608           if (connection)
01609             {
01610               /* The DBusConnection can't be finalized without taking
01611                * the shared_connections lock to remove it from the
01612                * hash.  So it's safe to ref the connection here.
01613                * However, it may be disconnected if the Disconnected
01614                * message hasn't been processed yet, in which case we
01615                * want to pretend it isn't in the hash and avoid
01616                * returning it.
01617                *
01618                * The idea is to avoid ever returning a disconnected connection
01619                * from dbus_connection_open(). We could just synchronously
01620                * drop our shared ref to the connection on connection disconnect,
01621                * and then assert here that the connection is connected, but
01622                * that causes reentrancy headaches.
01623                */
01624               CONNECTION_LOCK (connection);
01625               if (_dbus_connection_get_is_connected_unlocked (connection))
01626                 {
01627                   _dbus_connection_ref_unlocked (connection);
01628                   *result = connection;
01629                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01630                                  guid);
01631                 }
01632               else
01633                 {
01634                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01635                                  guid);
01636                 }
01637               CONNECTION_UNLOCK (connection);
01638             }
01639         }
01640       
01641       _DBUS_UNLOCK (shared_connections);
01642       return TRUE;
01643     }
01644 }
01645 
01646 static dbus_bool_t
01647 connection_record_shared_unlocked (DBusConnection *connection,
01648                                    const char     *guid)
01649 {
01650   char *guid_key;
01651   char *guid_in_connection;
01652 
01653   HAVE_LOCK_CHECK (connection);
01654   _dbus_assert (connection->server_guid == NULL);
01655   _dbus_assert (connection->shareable);
01656 
01657   /* get a hard ref on this connection, even if
01658    * we won't in fact store it in the hash, we still
01659    * need to hold a ref on it until it's disconnected.
01660    */
01661   _dbus_connection_ref_unlocked (connection);
01662 
01663   if (guid == NULL)
01664     {
01665       _DBUS_LOCK (shared_connections);
01666 
01667       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01668         {
01669           _DBUS_UNLOCK (shared_connections);
01670           return FALSE;
01671         }
01672 
01673       _DBUS_UNLOCK (shared_connections);
01674       return TRUE; /* don't store in the hash */
01675     }
01676   
01677   /* A separate copy of the key is required in the hash table, because
01678    * we don't have a lock on the connection when we are doing a hash
01679    * lookup.
01680    */
01681   
01682   guid_key = _dbus_strdup (guid);
01683   if (guid_key == NULL)
01684     return FALSE;
01685 
01686   guid_in_connection = _dbus_strdup (guid);
01687   if (guid_in_connection == NULL)
01688     {
01689       dbus_free (guid_key);
01690       return FALSE;
01691     }
01692   
01693   _DBUS_LOCK (shared_connections);
01694   _dbus_assert (shared_connections != NULL);
01695   
01696   if (!_dbus_hash_table_insert_string (shared_connections,
01697                                        guid_key, connection))
01698     {
01699       dbus_free (guid_key);
01700       dbus_free (guid_in_connection);
01701       _DBUS_UNLOCK (shared_connections);
01702       return FALSE;
01703     }
01704 
01705   connection->server_guid = guid_in_connection;
01706 
01707   _dbus_verbose ("stored connection to %s to be shared\n",
01708                  connection->server_guid);
01709   
01710   _DBUS_UNLOCK (shared_connections);
01711 
01712   _dbus_assert (connection->server_guid != NULL);
01713   
01714   return TRUE;
01715 }
01716 
01717 static void
01718 connection_forget_shared_unlocked (DBusConnection *connection)
01719 {
01720   HAVE_LOCK_CHECK (connection);
01721 
01722   if (!connection->shareable)
01723     return;
01724   
01725   _DBUS_LOCK (shared_connections);
01726       
01727   if (connection->server_guid != NULL)
01728     {
01729       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01730                      connection->server_guid);
01731       
01732       if (!_dbus_hash_table_remove_string (shared_connections,
01733                                            connection->server_guid))
01734         _dbus_assert_not_reached ("connection was not in the shared table");
01735       
01736       dbus_free (connection->server_guid);
01737       connection->server_guid = NULL;
01738     }
01739   else
01740     {
01741       _dbus_list_remove (&shared_connections_no_guid, connection);
01742     }
01743 
01744   _DBUS_UNLOCK (shared_connections);
01745   
01746   /* remove our reference held on all shareable connections */
01747   _dbus_connection_unref_unlocked (connection);
01748 }
01749 
01750 static DBusConnection*
01751 connection_try_from_address_entry (DBusAddressEntry *entry,
01752                                    DBusError        *error)
01753 {
01754   DBusTransport *transport;
01755   DBusConnection *connection;
01756 
01757   transport = _dbus_transport_open (entry, error);
01758 
01759   if (transport == NULL)
01760     {
01761       _DBUS_ASSERT_ERROR_IS_SET (error);
01762       return NULL;
01763     }
01764 
01765   connection = _dbus_connection_new_for_transport (transport);
01766 
01767   _dbus_transport_unref (transport);
01768   
01769   if (connection == NULL)
01770     {
01771       _DBUS_SET_OOM (error);
01772       return NULL;
01773     }
01774 
01775 #ifndef DBUS_DISABLE_CHECKS
01776   _dbus_assert (!connection->have_connection_lock);
01777 #endif
01778   return connection;
01779 }
01780 
01781 /*
01782  * If the shared parameter is true, then any existing connection will
01783  * be used (and if a new connection is created, it will be available
01784  * for use by others). If the shared parameter is false, a new
01785  * connection will always be created, and the new connection will
01786  * never be returned to other callers.
01787  *
01788  * @param address the address
01789  * @param shared whether the connection is shared or private
01790  * @param error error return
01791  * @returns the connection or #NULL on error
01792  */
01793 static DBusConnection*
01794 _dbus_connection_open_internal (const char     *address,
01795                                 dbus_bool_t     shared,
01796                                 DBusError      *error)
01797 {
01798   DBusConnection *connection;
01799   DBusAddressEntry **entries;
01800   DBusError tmp_error = DBUS_ERROR_INIT;
01801   DBusError first_error = DBUS_ERROR_INIT;
01802   int len, i;
01803 
01804   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01805 
01806   _dbus_verbose ("opening %s connection to: %s\n",
01807                  shared ? "shared" : "private", address);
01808   
01809   if (!dbus_parse_address (address, &entries, &len, error))
01810     return NULL;
01811 
01812   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01813   
01814   connection = NULL;
01815 
01816   for (i = 0; i < len; i++)
01817     {
01818       if (shared)
01819         {
01820           if (!connection_lookup_shared (entries[i], &connection))
01821             _DBUS_SET_OOM (&tmp_error);
01822         }
01823 
01824       if (connection == NULL)
01825         {
01826           connection = connection_try_from_address_entry (entries[i],
01827                                                           &tmp_error);
01828 
01829           if (connection != NULL && shared)
01830             {
01831               const char *guid;
01832                   
01833               connection->shareable = TRUE;
01834                   
01835               /* guid may be NULL */
01836               guid = dbus_address_entry_get_value (entries[i], "guid");
01837                   
01838               CONNECTION_LOCK (connection);
01839           
01840               if (!connection_record_shared_unlocked (connection, guid))
01841                 {
01842                   _DBUS_SET_OOM (&tmp_error);
01843                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01844                   dbus_connection_unref (connection);
01845                   connection = NULL;
01846                 }
01847               else
01848                 CONNECTION_UNLOCK (connection);
01849             }
01850         }
01851       
01852       if (connection)
01853         break;
01854 
01855       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01856       
01857       if (i == 0)
01858         dbus_move_error (&tmp_error, &first_error);
01859       else
01860         dbus_error_free (&tmp_error);
01861     }
01862   
01863   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01864   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01865   
01866   if (connection == NULL)
01867     {
01868       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01869       dbus_move_error (&first_error, error);
01870     }
01871   else
01872     dbus_error_free (&first_error);
01873   
01874   dbus_address_entries_free (entries);
01875   return connection;
01876 }
01877 
01886 void
01887 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01888 {
01889   _dbus_assert (connection != NULL);
01890   _dbus_assert (connection->generation == _dbus_current_generation);
01891 
01892   CONNECTION_LOCK (connection);
01893   _dbus_connection_close_possibly_shared_and_unlock (connection);
01894 }
01895 
01896 static DBusPreallocatedSend*
01897 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01898 {
01899   DBusPreallocatedSend *preallocated;
01900 
01901   HAVE_LOCK_CHECK (connection);
01902   
01903   _dbus_assert (connection != NULL);
01904   
01905   preallocated = dbus_new (DBusPreallocatedSend, 1);
01906   if (preallocated == NULL)
01907     return NULL;
01908 
01909   if (connection->link_cache != NULL)
01910     {
01911       preallocated->queue_link =
01912         _dbus_list_pop_first_link (&connection->link_cache);
01913       preallocated->queue_link->data = NULL;
01914     }
01915   else
01916     {
01917       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01918       if (preallocated->queue_link == NULL)
01919         goto failed_0;
01920     }
01921   
01922   if (connection->link_cache != NULL)
01923     {
01924       preallocated->counter_link =
01925         _dbus_list_pop_first_link (&connection->link_cache);
01926       preallocated->counter_link->data = connection->outgoing_counter;
01927     }
01928   else
01929     {
01930       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01931       if (preallocated->counter_link == NULL)
01932         goto failed_1;
01933     }
01934 
01935   _dbus_counter_ref (preallocated->counter_link->data);
01936 
01937   preallocated->connection = connection;
01938   
01939   return preallocated;
01940   
01941  failed_1:
01942   _dbus_list_free_link (preallocated->queue_link);
01943  failed_0:
01944   dbus_free (preallocated);
01945   
01946   return NULL;
01947 }
01948 
01949 /* Called with lock held, does not update dispatch status */
01950 static void
01951 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01952                                                        DBusPreallocatedSend *preallocated,
01953                                                        DBusMessage          *message,
01954                                                        dbus_uint32_t        *client_serial)
01955 {
01956   dbus_uint32_t serial;
01957   const char *sig;
01958 
01959   preallocated->queue_link->data = message;
01960   _dbus_list_prepend_link (&connection->outgoing_messages,
01961                            preallocated->queue_link);
01962 
01963   _dbus_message_add_size_counter_link (message,
01964                                        preallocated->counter_link);
01965 
01966   dbus_free (preallocated);
01967   preallocated = NULL;
01968   
01969   dbus_message_ref (message);
01970   
01971   connection->n_outgoing += 1;
01972 
01973   sig = dbus_message_get_signature (message);
01974   
01975   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01976                  message,
01977                  dbus_message_get_type (message),
01978                  dbus_message_get_path (message) ?
01979                  dbus_message_get_path (message) :
01980                  "no path",
01981                  dbus_message_get_interface (message) ?
01982                  dbus_message_get_interface (message) :
01983                  "no interface",
01984                  dbus_message_get_member (message) ?
01985                  dbus_message_get_member (message) :
01986                  "no member",
01987                  sig,
01988                  dbus_message_get_destination (message) ?
01989                  dbus_message_get_destination (message) :
01990                  "null",
01991                  connection,
01992                  connection->n_outgoing);
01993 
01994   if (dbus_message_get_serial (message) == 0)
01995     {
01996       serial = _dbus_connection_get_next_client_serial (connection);
01997       dbus_message_set_serial (message, serial);
01998       if (client_serial)
01999         *client_serial = serial;
02000     }
02001   else
02002     {
02003       if (client_serial)
02004         *client_serial = dbus_message_get_serial (message);
02005     }
02006 
02007   _dbus_verbose ("Message %p serial is %u\n",
02008                  message, dbus_message_get_serial (message));
02009   
02010   dbus_message_lock (message);
02011 
02012   /* Now we need to run an iteration to hopefully just write the messages
02013    * out immediately, and otherwise get them queued up
02014    */
02015   _dbus_connection_do_iteration_unlocked (connection,
02016                                           NULL,
02017                                           DBUS_ITERATION_DO_WRITING,
02018                                           -1);
02019 
02020   /* If stuff is still queued up, be sure we wake up the main loop */
02021   if (connection->n_outgoing > 0)
02022     _dbus_connection_wakeup_mainloop (connection);
02023 }
02024 
02025 static void
02026 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02027                                                DBusPreallocatedSend *preallocated,
02028                                                DBusMessage          *message,
02029                                                dbus_uint32_t        *client_serial)
02030 {
02031   DBusDispatchStatus status;
02032 
02033   HAVE_LOCK_CHECK (connection);
02034   
02035   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02036                                                          preallocated,
02037                                                          message, client_serial);
02038 
02039   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02040   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02041 
02042   /* this calls out to user code */
02043   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02044 }
02045 
02055 dbus_bool_t
02056 _dbus_connection_send_and_unlock (DBusConnection *connection,
02057                                   DBusMessage    *message,
02058                                   dbus_uint32_t  *client_serial)
02059 {
02060   DBusPreallocatedSend *preallocated;
02061 
02062   _dbus_assert (connection != NULL);
02063   _dbus_assert (message != NULL);
02064   
02065   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02066   if (preallocated == NULL)
02067     {
02068       CONNECTION_UNLOCK (connection);
02069       return FALSE;
02070     }
02071 
02072   _dbus_connection_send_preallocated_and_unlock (connection,
02073                                                  preallocated,
02074                                                  message,
02075                                                  client_serial);
02076   return TRUE;
02077 }
02078 
02103 void
02104 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02105 {
02106   CONNECTION_LOCK (connection);
02107   
02108   _dbus_assert (connection->refcount.value > 0);
02109 
02110   if (connection->refcount.value == 1)
02111     _dbus_connection_close_possibly_shared_and_unlock (connection);
02112   else
02113     CONNECTION_UNLOCK (connection);
02114 }
02115 
02116 
02126 static void
02127 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02128 {
02129   if (timeout_milliseconds == -1)
02130     _dbus_sleep_milliseconds (1000);
02131   else if (timeout_milliseconds < 100)
02132     ; /* just busy loop */
02133   else if (timeout_milliseconds <= 1000)
02134     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02135   else
02136     _dbus_sleep_milliseconds (1000);
02137 }
02138 
02139 static DBusMessage *
02140 generate_local_error_message (dbus_uint32_t serial, 
02141                               char *error_name, 
02142                               char *error_msg)
02143 {
02144   DBusMessage *message;
02145   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02146   if (!message)
02147     goto out;
02148 
02149   if (!dbus_message_set_error_name (message, error_name))
02150     {
02151       dbus_message_unref (message);
02152       message = NULL;
02153       goto out; 
02154     }
02155 
02156   dbus_message_set_no_reply (message, TRUE); 
02157 
02158   if (!dbus_message_set_reply_serial (message,
02159                                       serial))
02160     {
02161       dbus_message_unref (message);
02162       message = NULL;
02163       goto out;
02164     }
02165 
02166   if (error_msg != NULL)
02167     {
02168       DBusMessageIter iter;
02169 
02170       dbus_message_iter_init_append (message, &iter);
02171       if (!dbus_message_iter_append_basic (&iter,
02172                                            DBUS_TYPE_STRING,
02173                                            &error_msg))
02174         {
02175           dbus_message_unref (message);
02176           message = NULL;
02177           goto out;
02178         }
02179     }
02180 
02181  out:
02182   return message;
02183 }
02184 
02185 /*
02186  * Peek the incoming queue to see if we got reply for a specific serial
02187  */
02188 static dbus_bool_t
02189 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02190                                           dbus_uint32_t   client_serial)
02191 {
02192   DBusList *link;
02193   HAVE_LOCK_CHECK (connection);
02194 
02195   link = _dbus_list_get_first_link (&connection->incoming_messages);
02196 
02197   while (link != NULL)
02198     {
02199       DBusMessage *reply = link->data;
02200 
02201       if (dbus_message_get_reply_serial (reply) == client_serial)
02202         {
02203           _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02204           return TRUE;
02205         }
02206       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02207     }
02208 
02209   return FALSE;
02210 }
02211 
02212 /* This is slightly strange since we can pop a message here without
02213  * the dispatch lock.
02214  */
02215 static DBusMessage*
02216 check_for_reply_unlocked (DBusConnection *connection,
02217                           dbus_uint32_t   client_serial)
02218 {
02219   DBusList *link;
02220 
02221   HAVE_LOCK_CHECK (connection);
02222   
02223   link = _dbus_list_get_first_link (&connection->incoming_messages);
02224 
02225   while (link != NULL)
02226     {
02227       DBusMessage *reply = link->data;
02228 
02229       if (dbus_message_get_reply_serial (reply) == client_serial)
02230         {
02231           _dbus_list_remove_link (&connection->incoming_messages, link);
02232           connection->n_incoming  -= 1;
02233           return reply;
02234         }
02235       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02236     }
02237 
02238   return NULL;
02239 }
02240 
02241 static void
02242 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02243 {
02244    /* We can't iterate over the hash in the normal way since we'll be
02245     * dropping the lock for each item. So we restart the
02246     * iter each time as we drain the hash table.
02247     */
02248    
02249    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02250     {
02251       DBusPendingCall *pending;
02252       DBusHashIter iter;
02253       
02254       _dbus_hash_iter_init (connection->pending_replies, &iter);
02255       _dbus_hash_iter_next (&iter);
02256        
02257       pending = _dbus_hash_iter_get_value (&iter);
02258       _dbus_pending_call_ref_unlocked (pending);
02259        
02260       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02261                                                        connection);
02262 
02263       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02264           _dbus_connection_remove_timeout_unlocked (connection,
02265                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02266       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02267       _dbus_hash_iter_remove_entry (&iter);
02268 
02269       _dbus_pending_call_unref_and_unlock (pending);
02270       CONNECTION_LOCK (connection);
02271     }
02272   HAVE_LOCK_CHECK (connection);
02273 }
02274 
02275 static void
02276 complete_pending_call_and_unlock (DBusConnection  *connection,
02277                                   DBusPendingCall *pending,
02278                                   DBusMessage     *message)
02279 {
02280   _dbus_pending_call_set_reply_unlocked (pending, message);
02281   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02282   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02283  
02284   /* Must be called unlocked since it invokes app callback */
02285   _dbus_pending_call_complete (pending);
02286   dbus_pending_call_unref (pending);
02287 }
02288 
02289 static dbus_bool_t
02290 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02291                                               DBusPendingCall *pending)
02292 {
02293   DBusMessage *reply;
02294   DBusDispatchStatus status;
02295 
02296   reply = check_for_reply_unlocked (connection, 
02297                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02298   if (reply != NULL)
02299     {
02300       _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02301 
02302       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02303 
02304       complete_pending_call_and_unlock (connection, pending, reply);
02305       dbus_message_unref (reply);
02306 
02307       CONNECTION_LOCK (connection);
02308       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02309       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02310       dbus_pending_call_unref (pending);
02311 
02312       return TRUE;
02313     }
02314 
02315   return FALSE;
02316 }
02317 
02332 void
02333 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02334 {
02335   long start_tv_sec, start_tv_usec;
02336   long tv_sec, tv_usec;
02337   DBusDispatchStatus status;
02338   DBusConnection *connection;
02339   dbus_uint32_t client_serial;
02340   DBusTimeout *timeout;
02341   int timeout_milliseconds, elapsed_milliseconds;
02342 
02343   _dbus_assert (pending != NULL);
02344 
02345   if (dbus_pending_call_get_completed (pending))
02346     return;
02347 
02348   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02349 
02350   connection = _dbus_pending_call_get_connection_and_lock (pending);
02351   
02352   /* Flush message queue - note, can affect dispatch status */
02353   _dbus_connection_flush_unlocked (connection);
02354 
02355   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02356 
02357   /* note that timeout_milliseconds is limited to a smallish value
02358    * in _dbus_pending_call_new() so overflows aren't possible
02359    * below
02360    */
02361   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02362   if (timeout)
02363     {
02364       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02365       _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02366 
02367       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02368                      timeout_milliseconds,
02369                      client_serial,
02370                      start_tv_sec, start_tv_usec);
02371     }
02372   else
02373     {
02374       timeout_milliseconds = -1;
02375 
02376       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02377     }
02378 
02379   /* check to see if we already got the data off the socket */
02380   /* from another blocked pending call */
02381   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02382     return;
02383 
02384   /* Now we wait... */
02385   /* always block at least once as we know we don't have the reply yet */
02386   _dbus_connection_do_iteration_unlocked (connection,
02387                                           pending,
02388                                           DBUS_ITERATION_DO_READING |
02389                                           DBUS_ITERATION_BLOCK,
02390                                           timeout_milliseconds);
02391 
02392  recheck_status:
02393 
02394   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02395   
02396   HAVE_LOCK_CHECK (connection);
02397   
02398   /* queue messages and get status */
02399 
02400   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02401 
02402   /* the get_completed() is in case a dispatch() while we were blocking
02403    * got the reply instead of us.
02404    */
02405   if (_dbus_pending_call_get_completed_unlocked (pending))
02406     {
02407       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02408       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02409       dbus_pending_call_unref (pending);
02410       return;
02411     }
02412   
02413   if (status == DBUS_DISPATCH_DATA_REMAINS)
02414     {
02415       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02416         return;
02417     }
02418   
02419   _dbus_get_current_time (&tv_sec, &tv_usec);
02420   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02421           (tv_usec - start_tv_usec) / 1000;
02422   
02423   if (!_dbus_connection_get_is_connected_unlocked (connection))
02424     {
02425       DBusMessage *error_msg;
02426 
02427       error_msg = generate_local_error_message (client_serial,
02428                                                 DBUS_ERROR_DISCONNECTED, 
02429                                                 "Connection was disconnected before a reply was received"); 
02430 
02431       /* on OOM error_msg is set to NULL */
02432       complete_pending_call_and_unlock (connection, pending, error_msg);
02433       dbus_pending_call_unref (pending);
02434       return;
02435     }
02436   else if (connection->disconnect_message_link == NULL)
02437     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02438   else if (timeout == NULL)
02439     {
02440        if (status == DBUS_DISPATCH_NEED_MEMORY)
02441         {
02442           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02443            * we may already have a reply in the buffer and just can't process
02444            * it.
02445            */
02446           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02447 
02448           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02449         }
02450       else
02451         {          
02452           /* block again, we don't have the reply buffered yet. */
02453           _dbus_connection_do_iteration_unlocked (connection,
02454                                                   pending,
02455                                                   DBUS_ITERATION_DO_READING |
02456                                                   DBUS_ITERATION_BLOCK,
02457                                                   timeout_milliseconds - elapsed_milliseconds);
02458         }
02459 
02460       goto recheck_status;
02461     }
02462   else if (tv_sec < start_tv_sec)
02463     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02464   else if (elapsed_milliseconds < timeout_milliseconds)
02465     {
02466       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02467       
02468       if (status == DBUS_DISPATCH_NEED_MEMORY)
02469         {
02470           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02471            * we may already have a reply in the buffer and just can't process
02472            * it.
02473            */
02474           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02475 
02476           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02477         }
02478       else
02479         {          
02480           /* block again, we don't have the reply buffered yet. */
02481           _dbus_connection_do_iteration_unlocked (connection,
02482                                                   NULL,
02483                                                   DBUS_ITERATION_DO_READING |
02484                                                   DBUS_ITERATION_BLOCK,
02485                                                   timeout_milliseconds - elapsed_milliseconds);
02486         }
02487 
02488       goto recheck_status;
02489     }
02490 
02491   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02492                  elapsed_milliseconds);
02493 
02494   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02495   
02496   /* unlock and call user code */
02497   complete_pending_call_and_unlock (connection, pending, NULL);
02498 
02499   /* update user code on dispatch status */
02500   CONNECTION_LOCK (connection);
02501   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02502   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02503   dbus_pending_call_unref (pending);
02504 }
02505 
02542 DBusConnection*
02543 dbus_connection_open (const char     *address,
02544                       DBusError      *error)
02545 {
02546   DBusConnection *connection;
02547 
02548   _dbus_return_val_if_fail (address != NULL, NULL);
02549   _dbus_return_val_if_error_is_set (error, NULL);
02550 
02551   connection = _dbus_connection_open_internal (address,
02552                                                TRUE,
02553                                                error);
02554 
02555   return connection;
02556 }
02557 
02585 DBusConnection*
02586 dbus_connection_open_private (const char     *address,
02587                               DBusError      *error)
02588 {
02589   DBusConnection *connection;
02590 
02591   _dbus_return_val_if_fail (address != NULL, NULL);
02592   _dbus_return_val_if_error_is_set (error, NULL);
02593 
02594   connection = _dbus_connection_open_internal (address,
02595                                                FALSE,
02596                                                error);
02597 
02598   return connection;
02599 }
02600 
02607 DBusConnection *
02608 dbus_connection_ref (DBusConnection *connection)
02609 {
02610   _dbus_return_val_if_fail (connection != NULL, NULL);
02611   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02612   
02613   /* The connection lock is better than the global
02614    * lock in the atomic increment fallback
02615    */
02616   
02617 #ifdef DBUS_HAVE_ATOMIC_INT
02618   _dbus_atomic_inc (&connection->refcount);
02619 #else
02620   CONNECTION_LOCK (connection);
02621   _dbus_assert (connection->refcount.value > 0);
02622 
02623   connection->refcount.value += 1;
02624   CONNECTION_UNLOCK (connection);
02625 #endif
02626 
02627   return connection;
02628 }
02629 
02630 static void
02631 free_outgoing_message (void *element,
02632                        void *data)
02633 {
02634   DBusMessage *message = element;
02635   DBusConnection *connection = data;
02636 
02637   _dbus_message_remove_size_counter (message,
02638                                      connection->outgoing_counter,
02639                                      NULL);
02640   dbus_message_unref (message);
02641 }
02642 
02643 /* This is run without the mutex held, but after the last reference
02644  * to the connection has been dropped we should have no thread-related
02645  * problems
02646  */
02647 static void
02648 _dbus_connection_last_unref (DBusConnection *connection)
02649 {
02650   DBusList *link;
02651 
02652   _dbus_verbose ("Finalizing connection %p\n", connection);
02653   
02654   _dbus_assert (connection->refcount.value == 0);
02655   
02656   /* You have to disconnect the connection before unref:ing it. Otherwise
02657    * you won't get the disconnected message.
02658    */
02659   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02660   _dbus_assert (connection->server_guid == NULL);
02661   
02662   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02663   _dbus_object_tree_free_all_unlocked (connection->objects);
02664   
02665   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02666   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02667   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02668   
02669   _dbus_watch_list_free (connection->watches);
02670   connection->watches = NULL;
02671   
02672   _dbus_timeout_list_free (connection->timeouts);
02673   connection->timeouts = NULL;
02674 
02675   _dbus_data_slot_list_free (&connection->slot_list);
02676   
02677   link = _dbus_list_get_first_link (&connection->filter_list);
02678   while (link != NULL)
02679     {
02680       DBusMessageFilter *filter = link->data;
02681       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02682 
02683       filter->function = NULL;
02684       _dbus_message_filter_unref (filter); /* calls app callback */
02685       link->data = NULL;
02686       
02687       link = next;
02688     }
02689   _dbus_list_clear (&connection->filter_list);
02690   
02691   /* ---- Done with stuff that invokes application callbacks */
02692 
02693   _dbus_object_tree_unref (connection->objects);  
02694 
02695   _dbus_hash_table_unref (connection->pending_replies);
02696   connection->pending_replies = NULL;
02697   
02698   _dbus_list_clear (&connection->filter_list);
02699   
02700   _dbus_list_foreach (&connection->outgoing_messages,
02701                       free_outgoing_message,
02702                       connection);
02703   _dbus_list_clear (&connection->outgoing_messages);
02704   
02705   _dbus_list_foreach (&connection->incoming_messages,
02706                       (DBusForeachFunction) dbus_message_unref,
02707                       NULL);
02708   _dbus_list_clear (&connection->incoming_messages);
02709 
02710   _dbus_counter_unref (connection->outgoing_counter);
02711 
02712   _dbus_transport_unref (connection->transport);
02713 
02714   if (connection->disconnect_message_link)
02715     {
02716       DBusMessage *message = connection->disconnect_message_link->data;
02717       dbus_message_unref (message);
02718       _dbus_list_free_link (connection->disconnect_message_link);
02719     }
02720 
02721   _dbus_list_clear (&connection->link_cache);
02722   
02723   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02724   _dbus_condvar_free_at_location (&connection->io_path_cond);
02725 
02726   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02727   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02728 
02729   _dbus_mutex_free_at_location (&connection->mutex);
02730   
02731   dbus_free (connection);
02732 }
02733 
02753 void
02754 dbus_connection_unref (DBusConnection *connection)
02755 {
02756   dbus_bool_t last_unref;
02757 
02758   _dbus_return_if_fail (connection != NULL);
02759   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02760   
02761   /* The connection lock is better than the global
02762    * lock in the atomic increment fallback
02763    */
02764   
02765 #ifdef DBUS_HAVE_ATOMIC_INT
02766   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02767 #else
02768   CONNECTION_LOCK (connection);
02769   
02770   _dbus_assert (connection->refcount.value > 0);
02771 
02772   connection->refcount.value -= 1;
02773   last_unref = (connection->refcount.value == 0);
02774 
02775 #if 0
02776   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02777 #endif
02778   
02779   CONNECTION_UNLOCK (connection);
02780 #endif
02781   
02782   if (last_unref)
02783     {
02784 #ifndef DBUS_DISABLE_CHECKS
02785       if (_dbus_transport_get_is_connected (connection->transport))
02786         {
02787           _dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
02788                                    connection->shareable ?
02789                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02790                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02791           return;
02792         }
02793 #endif
02794       _dbus_connection_last_unref (connection);
02795     }
02796 }
02797 
02798 /*
02799  * Note that the transport can disconnect itself (other end drops us)
02800  * and in that case this function never runs. So this function must
02801  * not do anything more than disconnect the transport and update the
02802  * dispatch status.
02803  * 
02804  * If the transport self-disconnects, then we assume someone will
02805  * dispatch the connection to cause the dispatch status update.
02806  */
02807 static void
02808 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02809 {
02810   DBusDispatchStatus status;
02811 
02812   HAVE_LOCK_CHECK (connection);
02813   
02814   _dbus_verbose ("Disconnecting %p\n", connection);
02815 
02816   /* We need to ref because update_dispatch_status_and_unlock will unref
02817    * the connection if it was shared and libdbus was the only remaining
02818    * refcount holder.
02819    */
02820   _dbus_connection_ref_unlocked (connection);
02821   
02822   _dbus_transport_disconnect (connection->transport);
02823 
02824   /* This has the side effect of queuing the disconnect message link
02825    * (unless we don't have enough memory, possibly, so don't assert it).
02826    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02827    * should never again return the newly-disconnected connection.
02828    *
02829    * However, we only unref the shared connection and exit_on_disconnect when
02830    * the disconnect message reaches the head of the message queue,
02831    * NOT when it's first queued.
02832    */
02833   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02834 
02835   /* This calls out to user code */
02836   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02837 
02838   /* Could also call out to user code */
02839   dbus_connection_unref (connection);
02840 }
02841 
02884 void
02885 dbus_connection_close (DBusConnection *connection)
02886 {
02887   _dbus_return_if_fail (connection != NULL);
02888   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02889 
02890   CONNECTION_LOCK (connection);
02891 
02892 #ifndef DBUS_DISABLE_CHECKS
02893   if (connection->shareable)
02894     {
02895       CONNECTION_UNLOCK (connection);
02896 
02897       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02898       return;
02899     }
02900 #endif
02901   
02902   _dbus_connection_close_possibly_shared_and_unlock (connection);
02903 }
02904 
02905 static dbus_bool_t
02906 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02907 {
02908   HAVE_LOCK_CHECK (connection);
02909   return _dbus_transport_get_is_connected (connection->transport);
02910 }
02911 
02925 dbus_bool_t
02926 dbus_connection_get_is_connected (DBusConnection *connection)
02927 {
02928   dbus_bool_t res;
02929 
02930   _dbus_return_val_if_fail (connection != NULL, FALSE);
02931   
02932   CONNECTION_LOCK (connection);
02933   res = _dbus_connection_get_is_connected_unlocked (connection);
02934   CONNECTION_UNLOCK (connection);
02935   
02936   return res;
02937 }
02938 
02947 dbus_bool_t
02948 dbus_connection_get_is_authenticated (DBusConnection *connection)
02949 {
02950   dbus_bool_t res;
02951 
02952   _dbus_return_val_if_fail (connection != NULL, FALSE);
02953   
02954   CONNECTION_LOCK (connection);
02955   res = _dbus_transport_get_is_authenticated (connection->transport);
02956   CONNECTION_UNLOCK (connection);
02957   
02958   return res;
02959 }
02960 
02981 dbus_bool_t
02982 dbus_connection_get_is_anonymous (DBusConnection *connection)
02983 {
02984   dbus_bool_t res;
02985 
02986   _dbus_return_val_if_fail (connection != NULL, FALSE);
02987   
02988   CONNECTION_LOCK (connection);
02989   res = _dbus_transport_get_is_anonymous (connection->transport);
02990   CONNECTION_UNLOCK (connection);
02991   
02992   return res;
02993 }
02994 
03026 char*
03027 dbus_connection_get_server_id (DBusConnection *connection)
03028 {
03029   char *id;
03030 
03031   _dbus_return_val_if_fail (connection != NULL, NULL);
03032   
03033   CONNECTION_LOCK (connection);
03034   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03035   CONNECTION_UNLOCK (connection);
03036   
03037   return id;
03038 }
03039 
03053 void
03054 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03055                                         dbus_bool_t     exit_on_disconnect)
03056 {
03057   _dbus_return_if_fail (connection != NULL);
03058 
03059   CONNECTION_LOCK (connection);
03060   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03061   CONNECTION_UNLOCK (connection);
03062 }
03063 
03073 DBusPreallocatedSend*
03074 dbus_connection_preallocate_send (DBusConnection *connection)
03075 {
03076   DBusPreallocatedSend *preallocated;
03077 
03078   _dbus_return_val_if_fail (connection != NULL, NULL);
03079 
03080   CONNECTION_LOCK (connection);
03081   
03082   preallocated =
03083     _dbus_connection_preallocate_send_unlocked (connection);
03084 
03085   CONNECTION_UNLOCK (connection);
03086 
03087   return preallocated;
03088 }
03089 
03099 void
03100 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03101                                         DBusPreallocatedSend *preallocated)
03102 {
03103   _dbus_return_if_fail (connection != NULL);
03104   _dbus_return_if_fail (preallocated != NULL);  
03105   _dbus_return_if_fail (connection == preallocated->connection);
03106 
03107   _dbus_list_free_link (preallocated->queue_link);
03108   _dbus_counter_unref (preallocated->counter_link->data);
03109   _dbus_list_free_link (preallocated->counter_link);
03110   dbus_free (preallocated);
03111 }
03112 
03125 void
03126 dbus_connection_send_preallocated (DBusConnection       *connection,
03127                                    DBusPreallocatedSend *preallocated,
03128                                    DBusMessage          *message,
03129                                    dbus_uint32_t        *client_serial)
03130 {
03131   _dbus_return_if_fail (connection != NULL);
03132   _dbus_return_if_fail (preallocated != NULL);
03133   _dbus_return_if_fail (message != NULL);
03134   _dbus_return_if_fail (preallocated->connection == connection);
03135   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03136                         dbus_message_get_member (message) != NULL);
03137   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03138                         (dbus_message_get_interface (message) != NULL &&
03139                          dbus_message_get_member (message) != NULL));
03140   
03141   CONNECTION_LOCK (connection);
03142   _dbus_connection_send_preallocated_and_unlock (connection,
03143                                                  preallocated,
03144                                                  message, client_serial);
03145 }
03146 
03147 static dbus_bool_t
03148 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03149                                           DBusMessage    *message,
03150                                           dbus_uint32_t  *client_serial)
03151 {
03152   DBusPreallocatedSend *preallocated;
03153 
03154   _dbus_assert (connection != NULL);
03155   _dbus_assert (message != NULL);
03156   
03157   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03158   if (preallocated == NULL)
03159     return FALSE;
03160 
03161   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03162                                                          preallocated,
03163                                                          message,
03164                                                          client_serial);
03165   return TRUE;
03166 }
03167 
03195 dbus_bool_t
03196 dbus_connection_send (DBusConnection *connection,
03197                       DBusMessage    *message,
03198                       dbus_uint32_t  *serial)
03199 {
03200   _dbus_return_val_if_fail (connection != NULL, FALSE);
03201   _dbus_return_val_if_fail (message != NULL, FALSE);
03202 
03203   CONNECTION_LOCK (connection);
03204 
03205   return _dbus_connection_send_and_unlock (connection,
03206                                            message,
03207                                            serial);
03208 }
03209 
03210 static dbus_bool_t
03211 reply_handler_timeout (void *data)
03212 {
03213   DBusConnection *connection;
03214   DBusDispatchStatus status;
03215   DBusPendingCall *pending = data;
03216 
03217   connection = _dbus_pending_call_get_connection_and_lock (pending);
03218 
03219   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03220                                                    connection);
03221   _dbus_connection_remove_timeout_unlocked (connection,
03222                                             _dbus_pending_call_get_timeout_unlocked (pending));
03223   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03224 
03225   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03226   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03227 
03228   /* Unlocks, and calls out to user code */
03229   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03230   
03231   return TRUE;
03232 }
03233 
03269 dbus_bool_t
03270 dbus_connection_send_with_reply (DBusConnection     *connection,
03271                                  DBusMessage        *message,
03272                                  DBusPendingCall   **pending_return,
03273                                  int                 timeout_milliseconds)
03274 {
03275   DBusPendingCall *pending;
03276   dbus_int32_t serial = -1;
03277   DBusDispatchStatus status;
03278 
03279   _dbus_return_val_if_fail (connection != NULL, FALSE);
03280   _dbus_return_val_if_fail (message != NULL, FALSE);
03281   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03282 
03283   if (pending_return)
03284     *pending_return = NULL;
03285 
03286   CONNECTION_LOCK (connection);
03287 
03288    if (!_dbus_connection_get_is_connected_unlocked (connection))
03289     {
03290       CONNECTION_UNLOCK (connection);
03291 
03292       return TRUE;
03293     }
03294 
03295   pending = _dbus_pending_call_new_unlocked (connection,
03296                                              timeout_milliseconds,
03297                                              reply_handler_timeout);
03298 
03299   if (pending == NULL)
03300     {
03301       CONNECTION_UNLOCK (connection);
03302       return FALSE;
03303     }
03304 
03305   /* Assign a serial to the message */
03306   serial = dbus_message_get_serial (message);
03307   if (serial == 0)
03308     {
03309       serial = _dbus_connection_get_next_client_serial (connection);
03310       dbus_message_set_serial (message, serial);
03311     }
03312 
03313   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03314     goto error;
03315     
03316   /* Insert the serial in the pending replies hash;
03317    * hash takes a refcount on DBusPendingCall.
03318    * Also, add the timeout.
03319    */
03320   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03321                                                       pending))
03322     goto error;
03323  
03324   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03325     {
03326       _dbus_connection_detach_pending_call_and_unlock (connection,
03327                                                        pending);
03328       goto error_unlocked;
03329     }
03330 
03331   if (pending_return)
03332     *pending_return = pending; /* hand off refcount */
03333   else
03334     {
03335       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03336       /* we still have a ref to the pending call in this case, we unref
03337        * after unlocking, below
03338        */
03339     }
03340 
03341   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03342 
03343   /* this calls out to user code */
03344   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03345 
03346   if (pending_return == NULL)
03347     dbus_pending_call_unref (pending);
03348   
03349   return TRUE;
03350 
03351  error:
03352   CONNECTION_UNLOCK (connection);
03353  error_unlocked:
03354   dbus_pending_call_unref (pending);
03355   return FALSE;
03356 }
03357 
03388 DBusMessage*
03389 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03390                                            DBusMessage        *message,
03391                                            int                 timeout_milliseconds,
03392                                            DBusError          *error)
03393 {
03394   DBusMessage *reply;
03395   DBusPendingCall *pending;
03396   
03397   _dbus_return_val_if_fail (connection != NULL, NULL);
03398   _dbus_return_val_if_fail (message != NULL, NULL);
03399   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03400   _dbus_return_val_if_error_is_set (error, NULL);
03401   
03402   if (!dbus_connection_send_with_reply (connection, message,
03403                                         &pending, timeout_milliseconds))
03404     {
03405       _DBUS_SET_OOM (error);
03406       return NULL;
03407     }
03408 
03409   if (pending == NULL)
03410     {
03411       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03412       return NULL;
03413     }
03414   
03415   dbus_pending_call_block (pending);
03416 
03417   reply = dbus_pending_call_steal_reply (pending);
03418   dbus_pending_call_unref (pending);
03419 
03420   /* call_complete_and_unlock() called from pending_call_block() should
03421    * always fill this in.
03422    */
03423   _dbus_assert (reply != NULL);
03424   
03425    if (dbus_set_error_from_message (error, reply))
03426     {
03427       dbus_message_unref (reply);
03428       return NULL;
03429     }
03430   else
03431     return reply;
03432 }
03433 
03442 static DBusDispatchStatus
03443 _dbus_connection_flush_unlocked (DBusConnection *connection)
03444 {
03445   /* We have to specify DBUS_ITERATION_DO_READING here because
03446    * otherwise we could have two apps deadlock if they are both doing
03447    * a flush(), and the kernel buffers fill up. This could change the
03448    * dispatch status.
03449    */
03450   DBusDispatchStatus status;
03451 
03452   HAVE_LOCK_CHECK (connection);
03453   
03454   while (connection->n_outgoing > 0 &&
03455          _dbus_connection_get_is_connected_unlocked (connection))
03456     {
03457       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03458       HAVE_LOCK_CHECK (connection);
03459       _dbus_connection_do_iteration_unlocked (connection,
03460                                               NULL,
03461                                               DBUS_ITERATION_DO_READING |
03462                                               DBUS_ITERATION_DO_WRITING |
03463                                               DBUS_ITERATION_BLOCK,
03464                                               -1);
03465     }
03466 
03467   HAVE_LOCK_CHECK (connection);
03468   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03469   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03470 
03471   HAVE_LOCK_CHECK (connection);
03472   return status;
03473 }
03474 
03480 void
03481 dbus_connection_flush (DBusConnection *connection)
03482 {
03483   /* We have to specify DBUS_ITERATION_DO_READING here because
03484    * otherwise we could have two apps deadlock if they are both doing
03485    * a flush(), and the kernel buffers fill up. This could change the
03486    * dispatch status.
03487    */
03488   DBusDispatchStatus status;
03489 
03490   _dbus_return_if_fail (connection != NULL);
03491   
03492   CONNECTION_LOCK (connection);
03493 
03494   status = _dbus_connection_flush_unlocked (connection);
03495   
03496   HAVE_LOCK_CHECK (connection);
03497   /* Unlocks and calls out to user code */
03498   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03499 
03500   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03501 }
03502 
03513 static dbus_bool_t
03514 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03515                                      int             timeout_milliseconds, 
03516                                      dbus_bool_t     dispatch)
03517 {
03518   DBusDispatchStatus dstatus;
03519   dbus_bool_t progress_possible;
03520 
03521   /* Need to grab a ref here in case we're a private connection and
03522    * the user drops the last ref in a handler we call; see bug 
03523    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03524    */
03525   dbus_connection_ref (connection);
03526   dstatus = dbus_connection_get_dispatch_status (connection);
03527 
03528   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03529     {
03530       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03531       dbus_connection_dispatch (connection);
03532       CONNECTION_LOCK (connection);
03533     }
03534   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03535     {
03536       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03537       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03538       CONNECTION_LOCK (connection);
03539     }
03540   else
03541     {
03542       CONNECTION_LOCK (connection);
03543       if (_dbus_connection_get_is_connected_unlocked (connection))
03544         {
03545           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03546           _dbus_connection_do_iteration_unlocked (connection,
03547                                                   NULL,
03548                                                   DBUS_ITERATION_DO_READING |
03549                                                   DBUS_ITERATION_DO_WRITING |
03550                                                   DBUS_ITERATION_BLOCK,
03551                                                   timeout_milliseconds);
03552         }
03553     }
03554   
03555   HAVE_LOCK_CHECK (connection);
03556   /* If we can dispatch, we can make progress until the Disconnected message
03557    * has been processed; if we can only read/write, we can make progress
03558    * as long as the transport is open.
03559    */
03560   if (dispatch)
03561     progress_possible = connection->n_incoming != 0 ||
03562       connection->disconnect_message_link != NULL;
03563   else
03564     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03565 
03566   CONNECTION_UNLOCK (connection);
03567 
03568   dbus_connection_unref (connection);
03569 
03570   return progress_possible; /* TRUE if we can make more progress */
03571 }
03572 
03573 
03608 dbus_bool_t
03609 dbus_connection_read_write_dispatch (DBusConnection *connection,
03610                                      int             timeout_milliseconds)
03611 {
03612   _dbus_return_val_if_fail (connection != NULL, FALSE);
03613   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03614    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03615 }
03616 
03640 dbus_bool_t 
03641 dbus_connection_read_write (DBusConnection *connection, 
03642                             int             timeout_milliseconds) 
03643 { 
03644   _dbus_return_val_if_fail (connection != NULL, FALSE);
03645   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03646    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03647 }
03648 
03649 /* We need to call this anytime we pop the head of the queue, and then
03650  * update_dispatch_status_and_unlock needs to be called afterward
03651  * which will "process" the disconnected message and set
03652  * disconnected_message_processed.
03653  */
03654 static void
03655 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03656                                              DBusMessage    *head_of_queue)
03657 {
03658   HAVE_LOCK_CHECK (connection);
03659 
03660   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03661   if (connection->disconnect_message_link == NULL &&
03662       dbus_message_is_signal (head_of_queue,
03663                               DBUS_INTERFACE_LOCAL,
03664                               "Disconnected"))
03665     {
03666       connection->disconnected_message_arrived = TRUE;
03667     }
03668 }
03669 
03689 DBusMessage*
03690 dbus_connection_borrow_message (DBusConnection *connection)
03691 {
03692   DBusDispatchStatus status;
03693   DBusMessage *message;
03694 
03695   _dbus_return_val_if_fail (connection != NULL, NULL);
03696 
03697   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03698   
03699   /* this is called for the side effect that it queues
03700    * up any messages from the transport
03701    */
03702   status = dbus_connection_get_dispatch_status (connection);
03703   if (status != DBUS_DISPATCH_DATA_REMAINS)
03704     return NULL;
03705   
03706   CONNECTION_LOCK (connection);
03707 
03708   _dbus_connection_acquire_dispatch (connection);
03709 
03710   /* While a message is outstanding, the dispatch lock is held */
03711   _dbus_assert (connection->message_borrowed == NULL);
03712 
03713   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03714   
03715   message = connection->message_borrowed;
03716 
03717   check_disconnected_message_arrived_unlocked (connection, message);
03718   
03719   /* Note that we KEEP the dispatch lock until the message is returned */
03720   if (message == NULL)
03721     _dbus_connection_release_dispatch (connection);
03722 
03723   CONNECTION_UNLOCK (connection);
03724 
03725   /* We don't update dispatch status until it's returned or stolen */
03726   
03727   return message;
03728 }
03729 
03738 void
03739 dbus_connection_return_message (DBusConnection *connection,
03740                                 DBusMessage    *message)
03741 {
03742   DBusDispatchStatus status;
03743   
03744   _dbus_return_if_fail (connection != NULL);
03745   _dbus_return_if_fail (message != NULL);
03746   _dbus_return_if_fail (message == connection->message_borrowed);
03747   _dbus_return_if_fail (connection->dispatch_acquired);
03748   
03749   CONNECTION_LOCK (connection);
03750   
03751   _dbus_assert (message == connection->message_borrowed);
03752   
03753   connection->message_borrowed = NULL;
03754 
03755   _dbus_connection_release_dispatch (connection); 
03756 
03757   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03758   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03759 }
03760 
03770 void
03771 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03772                                         DBusMessage    *message)
03773 {
03774   DBusMessage *pop_message;
03775   DBusDispatchStatus status;
03776 
03777   _dbus_return_if_fail (connection != NULL);
03778   _dbus_return_if_fail (message != NULL);
03779   _dbus_return_if_fail (message == connection->message_borrowed);
03780   _dbus_return_if_fail (connection->dispatch_acquired);
03781   
03782   CONNECTION_LOCK (connection);
03783  
03784   _dbus_assert (message == connection->message_borrowed);
03785 
03786   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03787   _dbus_assert (message == pop_message);
03788   
03789   connection->n_incoming -= 1;
03790  
03791   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03792                  message, connection->n_incoming);
03793  
03794   connection->message_borrowed = NULL;
03795 
03796   _dbus_connection_release_dispatch (connection);
03797 
03798   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03799   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03800 }
03801 
03802 /* See dbus_connection_pop_message, but requires the caller to own
03803  * the lock before calling. May drop the lock while running.
03804  */
03805 static DBusList*
03806 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03807 {
03808   HAVE_LOCK_CHECK (connection);
03809   
03810   _dbus_assert (connection->message_borrowed == NULL);
03811   
03812   if (connection->n_incoming > 0)
03813     {
03814       DBusList *link;
03815 
03816       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03817       connection->n_incoming -= 1;
03818 
03819       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03820                      link->data,
03821                      dbus_message_get_type (link->data),
03822                      dbus_message_get_path (link->data) ?
03823                      dbus_message_get_path (link->data) :
03824                      "no path",
03825                      dbus_message_get_interface (link->data) ?
03826                      dbus_message_get_interface (link->data) :
03827                      "no interface",
03828                      dbus_message_get_member (link->data) ?
03829                      dbus_message_get_member (link->data) :
03830                      "no member",
03831                      dbus_message_get_signature (link->data),
03832                      connection, connection->n_incoming);
03833 
03834       check_disconnected_message_arrived_unlocked (connection, link->data);
03835       
03836       return link;
03837     }
03838   else
03839     return NULL;
03840 }
03841 
03842 /* See dbus_connection_pop_message, but requires the caller to own
03843  * the lock before calling. May drop the lock while running.
03844  */
03845 static DBusMessage*
03846 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03847 {
03848   DBusList *link;
03849 
03850   HAVE_LOCK_CHECK (connection);
03851   
03852   link = _dbus_connection_pop_message_link_unlocked (connection);
03853 
03854   if (link != NULL)
03855     {
03856       DBusMessage *message;
03857       
03858       message = link->data;
03859       
03860       _dbus_list_free_link (link);
03861       
03862       return message;
03863     }
03864   else
03865     return NULL;
03866 }
03867 
03868 static void
03869 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03870                                                 DBusList       *message_link)
03871 {
03872   HAVE_LOCK_CHECK (connection);
03873   
03874   _dbus_assert (message_link != NULL);
03875   /* You can't borrow a message while a link is outstanding */
03876   _dbus_assert (connection->message_borrowed == NULL);
03877   /* We had to have the dispatch lock across the pop/putback */
03878   _dbus_assert (connection->dispatch_acquired);
03879 
03880   _dbus_list_prepend_link (&connection->incoming_messages,
03881                            message_link);
03882   connection->n_incoming += 1;
03883 
03884   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03885                  message_link->data,
03886                  dbus_message_get_type (message_link->data),
03887                  dbus_message_get_interface (message_link->data) ?
03888                  dbus_message_get_interface (message_link->data) :
03889                  "no interface",
03890                  dbus_message_get_member (message_link->data) ?
03891                  dbus_message_get_member (message_link->data) :
03892                  "no member",
03893                  dbus_message_get_signature (message_link->data),
03894                  connection, connection->n_incoming);
03895 }
03896 
03916 DBusMessage*
03917 dbus_connection_pop_message (DBusConnection *connection)
03918 {
03919   DBusMessage *message;
03920   DBusDispatchStatus status;
03921 
03922   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03923   
03924   /* this is called for the side effect that it queues
03925    * up any messages from the transport
03926    */
03927   status = dbus_connection_get_dispatch_status (connection);
03928   if (status != DBUS_DISPATCH_DATA_REMAINS)
03929     return NULL;
03930   
03931   CONNECTION_LOCK (connection);
03932   _dbus_connection_acquire_dispatch (connection);
03933   HAVE_LOCK_CHECK (connection);
03934   
03935   message = _dbus_connection_pop_message_unlocked (connection);
03936 
03937   _dbus_verbose ("Returning popped message %p\n", message);    
03938 
03939   _dbus_connection_release_dispatch (connection);
03940 
03941   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03942   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03943   
03944   return message;
03945 }
03946 
03954 static void
03955 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03956 {
03957   HAVE_LOCK_CHECK (connection);
03958 
03959   _dbus_connection_ref_unlocked (connection);
03960   CONNECTION_UNLOCK (connection);
03961   
03962   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03963   _dbus_mutex_lock (connection->dispatch_mutex);
03964 
03965   while (connection->dispatch_acquired)
03966     {
03967       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03968       _dbus_condvar_wait (connection->dispatch_cond, 
03969                           connection->dispatch_mutex);
03970     }
03971   
03972   _dbus_assert (!connection->dispatch_acquired);
03973 
03974   connection->dispatch_acquired = TRUE;
03975 
03976   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03977   _dbus_mutex_unlock (connection->dispatch_mutex);
03978   
03979   CONNECTION_LOCK (connection);
03980   _dbus_connection_unref_unlocked (connection);
03981 }
03982 
03990 static void
03991 _dbus_connection_release_dispatch (DBusConnection *connection)
03992 {
03993   HAVE_LOCK_CHECK (connection);
03994   
03995   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03996   _dbus_mutex_lock (connection->dispatch_mutex);
03997   
03998   _dbus_assert (connection->dispatch_acquired);
03999 
04000   connection->dispatch_acquired = FALSE;
04001   _dbus_condvar_wake_one (connection->dispatch_cond);
04002 
04003   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
04004   _dbus_mutex_unlock (connection->dispatch_mutex);
04005 }
04006 
04007 static void
04008 _dbus_connection_failed_pop (DBusConnection *connection,
04009                              DBusList       *message_link)
04010 {
04011   _dbus_list_prepend_link (&connection->incoming_messages,
04012                            message_link);
04013   connection->n_incoming += 1;
04014 }
04015 
04016 /* Note this may be called multiple times since we don't track whether we already did it */
04017 static void
04018 notify_disconnected_unlocked (DBusConnection *connection)
04019 {
04020   HAVE_LOCK_CHECK (connection);
04021 
04022   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04023    * connection from dbus_bus_get(). We make the same guarantee for
04024    * dbus_connection_open() but in a different way since we don't want to
04025    * unref right here; we instead check for connectedness before returning
04026    * the connection from the hash.
04027    */
04028   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04029 
04030   /* Dump the outgoing queue, we aren't going to be able to
04031    * send it now, and we'd like accessors like
04032    * dbus_connection_get_outgoing_size() to be accurate.
04033    */
04034   if (connection->n_outgoing > 0)
04035     {
04036       DBusList *link;
04037       
04038       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04039                      connection->n_outgoing);
04040       
04041       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04042         {
04043           _dbus_connection_message_sent (connection, link->data);
04044         }
04045     } 
04046 }
04047 
04048 /* Note this may be called multiple times since we don't track whether we already did it */
04049 static DBusDispatchStatus
04050 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04051 {
04052   HAVE_LOCK_CHECK (connection);
04053   
04054   if (connection->disconnect_message_link != NULL)
04055     {
04056       _dbus_verbose ("Sending disconnect message from %s\n",
04057                      _DBUS_FUNCTION_NAME);
04058       
04059       /* If we have pending calls, queue their timeouts - we want the Disconnected
04060        * to be the last message, after these timeouts.
04061        */
04062       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04063       
04064       /* We haven't sent the disconnect message already,
04065        * and all real messages have been queued up.
04066        */
04067       _dbus_connection_queue_synthesized_message_link (connection,
04068                                                        connection->disconnect_message_link);
04069       connection->disconnect_message_link = NULL;
04070 
04071       return DBUS_DISPATCH_DATA_REMAINS;
04072     }
04073 
04074   return DBUS_DISPATCH_COMPLETE;
04075 }
04076 
04077 static DBusDispatchStatus
04078 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04079 {
04080   HAVE_LOCK_CHECK (connection);
04081   
04082   if (connection->n_incoming > 0)
04083     return DBUS_DISPATCH_DATA_REMAINS;
04084   else if (!_dbus_transport_queue_messages (connection->transport))
04085     return DBUS_DISPATCH_NEED_MEMORY;
04086   else
04087     {
04088       DBusDispatchStatus status;
04089       dbus_bool_t is_connected;
04090       
04091       status = _dbus_transport_get_dispatch_status (connection->transport);
04092       is_connected = _dbus_transport_get_is_connected (connection->transport);
04093 
04094       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04095                      DISPATCH_STATUS_NAME (status), is_connected);
04096       
04097       if (!is_connected)
04098         {
04099           /* It's possible this would be better done by having an explicit
04100            * notification from _dbus_transport_disconnect() that would
04101            * synchronously do this, instead of waiting for the next dispatch
04102            * status check. However, probably not good to change until it causes
04103            * a problem.
04104            */
04105           notify_disconnected_unlocked (connection);
04106 
04107           /* I'm not sure this is needed; the idea is that we want to
04108            * queue the Disconnected only after we've read all the
04109            * messages, but if we're disconnected maybe we are guaranteed
04110            * to have read them all ?
04111            */
04112           if (status == DBUS_DISPATCH_COMPLETE)
04113             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04114         }
04115       
04116       if (status != DBUS_DISPATCH_COMPLETE)
04117         return status;
04118       else if (connection->n_incoming > 0)
04119         return DBUS_DISPATCH_DATA_REMAINS;
04120       else
04121         return DBUS_DISPATCH_COMPLETE;
04122     }
04123 }
04124 
04125 static void
04126 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04127                                                     DBusDispatchStatus new_status)
04128 {
04129   dbus_bool_t changed;
04130   DBusDispatchStatusFunction function;
04131   void *data;
04132 
04133   HAVE_LOCK_CHECK (connection);
04134 
04135   _dbus_connection_ref_unlocked (connection);
04136 
04137   changed = new_status != connection->last_dispatch_status;
04138 
04139   connection->last_dispatch_status = new_status;
04140 
04141   function = connection->dispatch_status_function;
04142   data = connection->dispatch_status_data;
04143 
04144   if (connection->disconnected_message_arrived &&
04145       !connection->disconnected_message_processed)
04146     {
04147       connection->disconnected_message_processed = TRUE;
04148       
04149       /* this does an unref, but we have a ref
04150        * so we should not run the finalizer here
04151        * inside the lock.
04152        */
04153       connection_forget_shared_unlocked (connection);
04154 
04155       if (connection->exit_on_disconnect)
04156         {
04157           CONNECTION_UNLOCK (connection);            
04158           
04159           _dbus_verbose ("Exiting on Disconnected signal\n");
04160           _dbus_exit (1);
04161           _dbus_assert_not_reached ("Call to exit() returned");
04162         }
04163     }
04164   
04165   /* We drop the lock */
04166   CONNECTION_UNLOCK (connection);
04167   
04168   if (changed && function)
04169     {
04170       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04171                      connection, new_status,
04172                      DISPATCH_STATUS_NAME (new_status));
04173       (* function) (connection, new_status, data);      
04174     }
04175   
04176   dbus_connection_unref (connection);
04177 }
04178 
04204 DBusDispatchStatus
04205 dbus_connection_get_dispatch_status (DBusConnection *connection)
04206 {
04207   DBusDispatchStatus status;
04208 
04209   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04210 
04211   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04212   
04213   CONNECTION_LOCK (connection);
04214 
04215   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04216   
04217   CONNECTION_UNLOCK (connection);
04218 
04219   return status;
04220 }
04221 
04225 static DBusHandlerResult
04226 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04227                                                  DBusMessage    *message)
04228 {
04229   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04230     {
04231       /* This means we're letting the bus route this message */
04232       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04233     }
04234   else if (dbus_message_is_method_call (message,
04235                                         DBUS_INTERFACE_PEER,
04236                                         "Ping"))
04237     {
04238       DBusMessage *ret;
04239       dbus_bool_t sent;
04240       
04241       ret = dbus_message_new_method_return (message);
04242       if (ret == NULL)
04243         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04244      
04245       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04246 
04247       dbus_message_unref (ret);
04248 
04249       if (!sent)
04250         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04251       
04252       return DBUS_HANDLER_RESULT_HANDLED;
04253     }
04254   else if (dbus_message_is_method_call (message,
04255                                         DBUS_INTERFACE_PEER,
04256                                         "GetMachineId"))
04257     {
04258       DBusMessage *ret;
04259       dbus_bool_t sent;
04260       DBusString uuid;
04261       
04262       ret = dbus_message_new_method_return (message);
04263       if (ret == NULL)
04264         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04265 
04266       sent = FALSE;
04267       _dbus_string_init (&uuid);
04268       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04269         {
04270           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04271           if (dbus_message_append_args (ret,
04272                                         DBUS_TYPE_STRING, &v_STRING,
04273                                         DBUS_TYPE_INVALID))
04274             {
04275               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04276             }
04277         }
04278       _dbus_string_free (&uuid);
04279       
04280       dbus_message_unref (ret);
04281 
04282       if (!sent)
04283         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04284       
04285       return DBUS_HANDLER_RESULT_HANDLED;
04286     }
04287   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04288     {
04289       /* We need to bounce anything else with this interface, otherwise apps
04290        * could start extending the interface and when we added extensions
04291        * here to DBusConnection we'd break those apps.
04292        */
04293       
04294       DBusMessage *ret;
04295       dbus_bool_t sent;
04296       
04297       ret = dbus_message_new_error (message,
04298                                     DBUS_ERROR_UNKNOWN_METHOD,
04299                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04300       if (ret == NULL)
04301         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04302       
04303       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04304       
04305       dbus_message_unref (ret);
04306       
04307       if (!sent)
04308         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04309       
04310       return DBUS_HANDLER_RESULT_HANDLED;
04311     }
04312   else
04313     {
04314       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04315     }
04316 }
04317 
04324 static DBusHandlerResult
04325 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04326                                                            DBusMessage    *message)
04327 {
04328   /* We just run one filter for now but have the option to run more
04329      if the spec calls for it in the future */
04330 
04331   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04332 }
04333 
04376 DBusDispatchStatus
04377 dbus_connection_dispatch (DBusConnection *connection)
04378 {
04379   DBusMessage *message;
04380   DBusList *link, *filter_list_copy, *message_link;
04381   DBusHandlerResult result;
04382   DBusPendingCall *pending;
04383   dbus_int32_t reply_serial;
04384   DBusDispatchStatus status;
04385 
04386   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04387 
04388   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04389   
04390   CONNECTION_LOCK (connection);
04391   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04392   if (status != DBUS_DISPATCH_DATA_REMAINS)
04393     {
04394       /* unlocks and calls out to user code */
04395       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04396       return status;
04397     }
04398   
04399   /* We need to ref the connection since the callback could potentially
04400    * drop the last ref to it
04401    */
04402   _dbus_connection_ref_unlocked (connection);
04403 
04404   _dbus_connection_acquire_dispatch (connection);
04405   HAVE_LOCK_CHECK (connection);
04406 
04407   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04408   if (message_link == NULL)
04409     {
04410       /* another thread dispatched our stuff */
04411 
04412       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04413       
04414       _dbus_connection_release_dispatch (connection);
04415 
04416       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04417 
04418       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04419       
04420       dbus_connection_unref (connection);
04421       
04422       return status;
04423     }
04424 
04425   message = message_link->data;
04426 
04427   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04428                  message,
04429                  dbus_message_get_type (message),
04430                  dbus_message_get_interface (message) ?
04431                  dbus_message_get_interface (message) :
04432                  "no interface",
04433                  dbus_message_get_member (message) ?
04434                  dbus_message_get_member (message) :
04435                  "no member",
04436                  dbus_message_get_signature (message));
04437 
04438   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04439   
04440   /* Pending call handling must be first, because if you do
04441    * dbus_connection_send_with_reply_and_block() or
04442    * dbus_pending_call_block() then no handlers/filters will be run on
04443    * the reply. We want consistent semantics in the case where we
04444    * dbus_connection_dispatch() the reply.
04445    */
04446   
04447   reply_serial = dbus_message_get_reply_serial (message);
04448   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04449                                          reply_serial);
04450   if (pending)
04451     {
04452       _dbus_verbose ("Dispatching a pending reply\n");
04453       complete_pending_call_and_unlock (connection, pending, message);
04454       pending = NULL; /* it's probably unref'd */
04455       
04456       CONNECTION_LOCK (connection);
04457       _dbus_verbose ("pending call completed in dispatch\n");
04458       result = DBUS_HANDLER_RESULT_HANDLED;
04459       goto out;
04460     }
04461 
04462   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04463   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04464     goto out;
04465  
04466   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04467     {
04468       _dbus_connection_release_dispatch (connection);
04469       HAVE_LOCK_CHECK (connection);
04470       
04471       _dbus_connection_failed_pop (connection, message_link);
04472 
04473       /* unlocks and calls user code */
04474       _dbus_connection_update_dispatch_status_and_unlock (connection,
04475                                                           DBUS_DISPATCH_NEED_MEMORY);
04476 
04477       if (pending)
04478         dbus_pending_call_unref (pending);
04479       dbus_connection_unref (connection);
04480       
04481       return DBUS_DISPATCH_NEED_MEMORY;
04482     }
04483   
04484   _dbus_list_foreach (&filter_list_copy,
04485                       (DBusForeachFunction)_dbus_message_filter_ref,
04486                       NULL);
04487 
04488   /* We're still protected from dispatch() reentrancy here
04489    * since we acquired the dispatcher
04490    */
04491   CONNECTION_UNLOCK (connection);
04492   
04493   link = _dbus_list_get_first_link (&filter_list_copy);
04494   while (link != NULL)
04495     {
04496       DBusMessageFilter *filter = link->data;
04497       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04498 
04499       if (filter->function == NULL)
04500         {
04501           _dbus_verbose ("  filter was removed in a callback function\n");
04502           link = next;
04503           continue;
04504         }
04505 
04506       _dbus_verbose ("  running filter on message %p\n", message);
04507       result = (* filter->function) (connection, message, filter->user_data);
04508 
04509       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04510         break;
04511 
04512       link = next;
04513     }
04514 
04515   _dbus_list_foreach (&filter_list_copy,
04516                       (DBusForeachFunction)_dbus_message_filter_unref,
04517                       NULL);
04518   _dbus_list_clear (&filter_list_copy);
04519   
04520   CONNECTION_LOCK (connection);
04521 
04522   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04523     {
04524       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04525       goto out;
04526     }
04527   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04528     {
04529       _dbus_verbose ("filter handled message in dispatch\n");
04530       goto out;
04531     }
04532 
04533   /* We're still protected from dispatch() reentrancy here
04534    * since we acquired the dispatcher
04535    */
04536   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
04537                  message,
04538                  dbus_message_get_type (message),
04539                  dbus_message_get_interface (message) ?
04540                  dbus_message_get_interface (message) :
04541                  "no interface",
04542                  dbus_message_get_member (message) ?
04543                  dbus_message_get_member (message) :
04544                  "no member",
04545                  dbus_message_get_signature (message));
04546 
04547   HAVE_LOCK_CHECK (connection);
04548   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04549                                                   message);
04550   
04551   CONNECTION_LOCK (connection);
04552 
04553   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04554     {
04555       _dbus_verbose ("object tree handled message in dispatch\n");
04556       goto out;
04557     }
04558 
04559   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04560     {
04561       DBusMessage *reply;
04562       DBusString str;
04563       DBusPreallocatedSend *preallocated;
04564 
04565       _dbus_verbose ("  sending error %s\n",
04566                      DBUS_ERROR_UNKNOWN_METHOD);
04567       
04568       if (!_dbus_string_init (&str))
04569         {
04570           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04571           _dbus_verbose ("no memory for error string in dispatch\n");
04572           goto out;
04573         }
04574               
04575       if (!_dbus_string_append_printf (&str,
04576                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04577                                        dbus_message_get_member (message),
04578                                        dbus_message_get_signature (message),
04579                                        dbus_message_get_interface (message)))
04580         {
04581           _dbus_string_free (&str);
04582           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04583           _dbus_verbose ("no memory for error string in dispatch\n");
04584           goto out;
04585         }
04586       
04587       reply = dbus_message_new_error (message,
04588                                       DBUS_ERROR_UNKNOWN_METHOD,
04589                                       _dbus_string_get_const_data (&str));
04590       _dbus_string_free (&str);
04591 
04592       if (reply == NULL)
04593         {
04594           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04595           _dbus_verbose ("no memory for error reply in dispatch\n");
04596           goto out;
04597         }
04598       
04599       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04600 
04601       if (preallocated == NULL)
04602         {
04603           dbus_message_unref (reply);
04604           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04605           _dbus_verbose ("no memory for error send in dispatch\n");
04606           goto out;
04607         }
04608 
04609       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04610                                                              reply, NULL);
04611 
04612       dbus_message_unref (reply);
04613       
04614       result = DBUS_HANDLER_RESULT_HANDLED;
04615     }
04616   
04617   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04618                  dbus_message_get_type (message),
04619                  dbus_message_get_interface (message) ?
04620                  dbus_message_get_interface (message) :
04621                  "no interface",
04622                  dbus_message_get_member (message) ?
04623                  dbus_message_get_member (message) :
04624                  "no member",
04625                  dbus_message_get_signature (message),
04626                  connection);
04627   
04628  out:
04629   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04630     {
04631       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04632       
04633       /* Put message back, and we'll start over.
04634        * Yes this means handlers must be idempotent if they
04635        * don't return HANDLED; c'est la vie.
04636        */
04637       _dbus_connection_putback_message_link_unlocked (connection,
04638                                                       message_link);
04639     }
04640   else
04641     {
04642       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04643       
04644       _dbus_list_free_link (message_link);
04645       dbus_message_unref (message); /* don't want the message to count in max message limits
04646                                      * in computing dispatch status below
04647                                      */
04648     }
04649   
04650   _dbus_connection_release_dispatch (connection);
04651   HAVE_LOCK_CHECK (connection);
04652 
04653   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04654   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04655 
04656   /* unlocks and calls user code */
04657   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04658   
04659   dbus_connection_unref (connection);
04660   
04661   return status;
04662 }
04663 
04723 dbus_bool_t
04724 dbus_connection_set_watch_functions (DBusConnection              *connection,
04725                                      DBusAddWatchFunction         add_function,
04726                                      DBusRemoveWatchFunction      remove_function,
04727                                      DBusWatchToggledFunction     toggled_function,
04728                                      void                        *data,
04729                                      DBusFreeFunction             free_data_function)
04730 {
04731   dbus_bool_t retval;
04732   DBusWatchList *watches;
04733 
04734   _dbus_return_val_if_fail (connection != NULL, FALSE);
04735   
04736   CONNECTION_LOCK (connection);
04737 
04738 #ifndef DBUS_DISABLE_CHECKS
04739   if (connection->watches == NULL)
04740     {
04741       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04742                                _DBUS_FUNCTION_NAME);
04743       return FALSE;
04744     }
04745 #endif
04746   
04747   /* ref connection for slightly better reentrancy */
04748   _dbus_connection_ref_unlocked (connection);
04749 
04750   /* This can call back into user code, and we need to drop the
04751    * connection lock when it does. This is kind of a lame
04752    * way to do it.
04753    */
04754   watches = connection->watches;
04755   connection->watches = NULL;
04756   CONNECTION_UNLOCK (connection);
04757 
04758   retval = _dbus_watch_list_set_functions (watches,
04759                                            add_function, remove_function,
04760                                            toggled_function,
04761                                            data, free_data_function);
04762   CONNECTION_LOCK (connection);
04763   connection->watches = watches;
04764   
04765   CONNECTION_UNLOCK (connection);
04766   /* drop our paranoid refcount */
04767   dbus_connection_unref (connection);
04768   
04769   return retval;
04770 }
04771 
04805 dbus_bool_t
04806 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04807                                          DBusAddTimeoutFunction     add_function,
04808                                          DBusRemoveTimeoutFunction  remove_function,
04809                                          DBusTimeoutToggledFunction toggled_function,
04810                                          void                      *data,
04811                                          DBusFreeFunction           free_data_function)
04812 {
04813   dbus_bool_t retval;
04814   DBusTimeoutList *timeouts;
04815 
04816   _dbus_return_val_if_fail (connection != NULL, FALSE);
04817   
04818   CONNECTION_LOCK (connection);
04819 
04820 #ifndef DBUS_DISABLE_CHECKS
04821   if (connection->timeouts == NULL)
04822     {
04823       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04824                                _DBUS_FUNCTION_NAME);
04825       return FALSE;
04826     }
04827 #endif
04828   
04829   /* ref connection for slightly better reentrancy */
04830   _dbus_connection_ref_unlocked (connection);
04831 
04832   timeouts = connection->timeouts;
04833   connection->timeouts = NULL;
04834   CONNECTION_UNLOCK (connection);
04835   
04836   retval = _dbus_timeout_list_set_functions (timeouts,
04837                                              add_function, remove_function,
04838                                              toggled_function,
04839                                              data, free_data_function);
04840   CONNECTION_LOCK (connection);
04841   connection->timeouts = timeouts;
04842   
04843   CONNECTION_UNLOCK (connection);
04844   /* drop our paranoid refcount */
04845   dbus_connection_unref (connection);
04846 
04847   return retval;
04848 }
04849 
04864 void
04865 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04866                                           DBusWakeupMainFunction     wakeup_main_function,
04867                                           void                      *data,
04868                                           DBusFreeFunction           free_data_function)
04869 {
04870   void *old_data;
04871   DBusFreeFunction old_free_data;
04872 
04873   _dbus_return_if_fail (connection != NULL);
04874   
04875   CONNECTION_LOCK (connection);
04876   old_data = connection->wakeup_main_data;
04877   old_free_data = connection->free_wakeup_main_data;
04878 
04879   connection->wakeup_main_function = wakeup_main_function;
04880   connection->wakeup_main_data = data;
04881   connection->free_wakeup_main_data = free_data_function;
04882   
04883   CONNECTION_UNLOCK (connection);
04884 
04885   /* Callback outside the lock */
04886   if (old_free_data)
04887     (*old_free_data) (old_data);
04888 }
04889 
04910 void
04911 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04912                                               DBusDispatchStatusFunction  function,
04913                                               void                       *data,
04914                                               DBusFreeFunction            free_data_function)
04915 {
04916   void *old_data;
04917   DBusFreeFunction old_free_data;
04918 
04919   _dbus_return_if_fail (connection != NULL);
04920   
04921   CONNECTION_LOCK (connection);
04922   old_data = connection->dispatch_status_data;
04923   old_free_data = connection->free_dispatch_status_data;
04924 
04925   connection->dispatch_status_function = function;
04926   connection->dispatch_status_data = data;
04927   connection->free_dispatch_status_data = free_data_function;
04928   
04929   CONNECTION_UNLOCK (connection);
04930 
04931   /* Callback outside the lock */
04932   if (old_free_data)
04933     (*old_free_data) (old_data);
04934 }
04935 
04955 dbus_bool_t
04956 dbus_connection_get_unix_fd (DBusConnection *connection,
04957                              int            *fd)
04958 {
04959   _dbus_return_val_if_fail (connection != NULL, FALSE);
04960   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04961 
04962 #ifdef DBUS_WIN
04963   /* FIXME do this on a lower level */
04964   return FALSE;
04965 #endif
04966   
04967   return dbus_connection_get_socket(connection, fd);
04968 }
04969 
04985 dbus_bool_t
04986 dbus_connection_get_socket(DBusConnection              *connection,
04987                            int                         *fd)
04988 {
04989   dbus_bool_t retval;
04990 
04991   _dbus_return_val_if_fail (connection != NULL, FALSE);
04992   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04993   
04994   CONNECTION_LOCK (connection);
04995   
04996   retval = _dbus_transport_get_socket_fd (connection->transport,
04997                                           fd);
04998 
04999   CONNECTION_UNLOCK (connection);
05000 
05001   return retval;
05002 }
05003 
05004 
05027 dbus_bool_t
05028 dbus_connection_get_unix_user (DBusConnection *connection,
05029                                unsigned long  *uid)
05030 {
05031   dbus_bool_t result;
05032 
05033   _dbus_return_val_if_fail (connection != NULL, FALSE);
05034   _dbus_return_val_if_fail (uid != NULL, FALSE);
05035   
05036   CONNECTION_LOCK (connection);
05037 
05038   if (!_dbus_transport_get_is_authenticated (connection->transport))
05039     result = FALSE;
05040   else
05041     result = _dbus_transport_get_unix_user (connection->transport,
05042                                             uid);
05043 
05044 #ifdef DBUS_WIN
05045   _dbus_assert (!result);
05046 #endif
05047   
05048   CONNECTION_UNLOCK (connection);
05049 
05050   return result;
05051 }
05052 
05063 dbus_bool_t
05064 dbus_connection_get_unix_process_id (DBusConnection *connection,
05065                                      unsigned long  *pid)
05066 {
05067   dbus_bool_t result;
05068 
05069   _dbus_return_val_if_fail (connection != NULL, FALSE);
05070   _dbus_return_val_if_fail (pid != NULL, FALSE);
05071   
05072   CONNECTION_LOCK (connection);
05073 
05074   if (!_dbus_transport_get_is_authenticated (connection->transport))
05075     result = FALSE;
05076   else
05077     result = _dbus_transport_get_unix_process_id (connection->transport,
05078                                                   pid);
05079 #ifdef DBUS_WIN
05080   _dbus_assert (!result);
05081 #endif
05082   
05083   CONNECTION_UNLOCK (connection);
05084 
05085   return result;
05086 }
05087 
05098 dbus_bool_t
05099 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05100                                             void          **data,
05101                                             dbus_int32_t   *data_size)
05102 {
05103   dbus_bool_t result;
05104 
05105   _dbus_return_val_if_fail (connection != NULL, FALSE);
05106   _dbus_return_val_if_fail (data != NULL, FALSE);
05107   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05108   
05109   CONNECTION_LOCK (connection);
05110 
05111   if (!_dbus_transport_get_is_authenticated (connection->transport))
05112     result = FALSE;
05113   else
05114     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05115                                                          data,
05116                                                          data_size);
05117   CONNECTION_UNLOCK (connection);
05118 
05119   return result;
05120 }
05121 
05144 void
05145 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05146                                         DBusAllowUnixUserFunction   function,
05147                                         void                       *data,
05148                                         DBusFreeFunction            free_data_function)
05149 {
05150   void *old_data = NULL;
05151   DBusFreeFunction old_free_function = NULL;
05152 
05153   _dbus_return_if_fail (connection != NULL);
05154   
05155   CONNECTION_LOCK (connection);
05156   _dbus_transport_set_unix_user_function (connection->transport,
05157                                           function, data, free_data_function,
05158                                           &old_data, &old_free_function);
05159   CONNECTION_UNLOCK (connection);
05160 
05161   if (old_free_function != NULL)
05162     (* old_free_function) (old_data);
05163 }
05164 
05196 dbus_bool_t
05197 dbus_connection_get_windows_user (DBusConnection             *connection,
05198                                   char                      **windows_sid_p)
05199 {
05200   dbus_bool_t result;
05201 
05202   _dbus_return_val_if_fail (connection != NULL, FALSE);
05203   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05204   
05205   CONNECTION_LOCK (connection);
05206 
05207   if (!_dbus_transport_get_is_authenticated (connection->transport))
05208     result = FALSE;
05209   else
05210     result = _dbus_transport_get_windows_user (connection->transport,
05211                                                windows_sid_p);
05212 
05213 #ifdef DBUS_UNIX
05214   _dbus_assert (!result);
05215 #endif
05216   
05217   CONNECTION_UNLOCK (connection);
05218 
05219   return result;
05220 }
05221 
05243 void
05244 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05245                                            DBusAllowWindowsUserFunction function,
05246                                            void                        *data,
05247                                            DBusFreeFunction             free_data_function)
05248 {
05249   void *old_data = NULL;
05250   DBusFreeFunction old_free_function = NULL;
05251 
05252   _dbus_return_if_fail (connection != NULL);
05253   
05254   CONNECTION_LOCK (connection);
05255   _dbus_transport_set_windows_user_function (connection->transport,
05256                                              function, data, free_data_function,
05257                                              &old_data, &old_free_function);
05258   CONNECTION_UNLOCK (connection);
05259 
05260   if (old_free_function != NULL)
05261     (* old_free_function) (old_data);
05262 }
05263 
05290 void
05291 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05292                                      dbus_bool_t                 value)
05293 {
05294   _dbus_return_if_fail (connection != NULL);
05295   
05296   CONNECTION_LOCK (connection);
05297   _dbus_transport_set_allow_anonymous (connection->transport, value);
05298   CONNECTION_UNLOCK (connection);
05299 }
05300 
05318 void
05319 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05320                                          dbus_bool_t                 value)
05321 {
05322   _dbus_return_if_fail (connection != NULL);
05323   
05324   CONNECTION_LOCK (connection);
05325   connection->route_peer_messages = TRUE;
05326   CONNECTION_UNLOCK (connection);
05327 }
05328 
05350 dbus_bool_t
05351 dbus_connection_add_filter (DBusConnection            *connection,
05352                             DBusHandleMessageFunction  function,
05353                             void                      *user_data,
05354                             DBusFreeFunction           free_data_function)
05355 {
05356   DBusMessageFilter *filter;
05357   
05358   _dbus_return_val_if_fail (connection != NULL, FALSE);
05359   _dbus_return_val_if_fail (function != NULL, FALSE);
05360 
05361   filter = dbus_new0 (DBusMessageFilter, 1);
05362   if (filter == NULL)
05363     return FALSE;
05364 
05365   filter->refcount.value = 1;
05366   
05367   CONNECTION_LOCK (connection);
05368 
05369   if (!_dbus_list_append (&connection->filter_list,
05370                           filter))
05371     {
05372       _dbus_message_filter_unref (filter);
05373       CONNECTION_UNLOCK (connection);
05374       return FALSE;
05375     }
05376 
05377   /* Fill in filter after all memory allocated,
05378    * so we don't run the free_user_data_function
05379    * if the add_filter() fails
05380    */
05381   
05382   filter->function = function;
05383   filter->user_data = user_data;
05384   filter->free_user_data_function = free_data_function;
05385         
05386   CONNECTION_UNLOCK (connection);
05387   return TRUE;
05388 }
05389 
05402 void
05403 dbus_connection_remove_filter (DBusConnection            *connection,
05404                                DBusHandleMessageFunction  function,
05405                                void                      *user_data)
05406 {
05407   DBusList *link;
05408   DBusMessageFilter *filter;
05409   
05410   _dbus_return_if_fail (connection != NULL);
05411   _dbus_return_if_fail (function != NULL);
05412   
05413   CONNECTION_LOCK (connection);
05414 
05415   filter = NULL;
05416   
05417   link = _dbus_list_get_last_link (&connection->filter_list);
05418   while (link != NULL)
05419     {
05420       filter = link->data;
05421 
05422       if (filter->function == function &&
05423           filter->user_data == user_data)
05424         {
05425           _dbus_list_remove_link (&connection->filter_list, link);
05426           filter->function = NULL;
05427           
05428           break;
05429         }
05430         
05431       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05432       filter = NULL;
05433     }
05434   
05435   CONNECTION_UNLOCK (connection);
05436 
05437 #ifndef DBUS_DISABLE_CHECKS
05438   if (filter == NULL)
05439     {
05440       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05441                                function, user_data);
05442       return;
05443     }
05444 #endif
05445   
05446   /* Call application code */
05447   if (filter->free_user_data_function)
05448     (* filter->free_user_data_function) (filter->user_data);
05449 
05450   filter->free_user_data_function = NULL;
05451   filter->user_data = NULL;
05452   
05453   _dbus_message_filter_unref (filter);
05454 }
05455 
05468 dbus_bool_t
05469 dbus_connection_try_register_object_path (DBusConnection              *connection,
05470                                           const char                  *path,
05471                                           const DBusObjectPathVTable  *vtable,
05472                                           void                        *user_data,
05473                                           DBusError                   *error)
05474 {
05475   char **decomposed_path;
05476   dbus_bool_t retval;
05477   
05478   _dbus_return_val_if_fail (connection != NULL, FALSE);
05479   _dbus_return_val_if_fail (path != NULL, FALSE);
05480   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05481   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05482 
05483   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05484     return FALSE;
05485 
05486   CONNECTION_LOCK (connection);
05487 
05488   retval = _dbus_object_tree_register (connection->objects,
05489                                        FALSE,
05490                                        (const char **) decomposed_path, vtable,
05491                                        user_data, error);
05492 
05493   CONNECTION_UNLOCK (connection);
05494 
05495   dbus_free_string_array (decomposed_path);
05496 
05497   return retval;
05498 }
05499 
05514 dbus_bool_t
05515 dbus_connection_register_object_path (DBusConnection              *connection,
05516                                       const char                  *path,
05517                                       const DBusObjectPathVTable  *vtable,
05518                                       void                        *user_data)
05519 {
05520   char **decomposed_path;
05521   dbus_bool_t retval;
05522   DBusError error = DBUS_ERROR_INIT;
05523 
05524   _dbus_return_val_if_fail (connection != NULL, FALSE);
05525   _dbus_return_val_if_fail (path != NULL, FALSE);
05526   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05527   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05528 
05529   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05530     return FALSE;
05531 
05532   CONNECTION_LOCK (connection);
05533 
05534   retval = _dbus_object_tree_register (connection->objects,
05535                                        FALSE,
05536                                        (const char **) decomposed_path, vtable,
05537                                        user_data, &error);
05538 
05539   CONNECTION_UNLOCK (connection);
05540 
05541   dbus_free_string_array (decomposed_path);
05542 
05543   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05544     {
05545       _dbus_warn ("%s\n", error.message);
05546       dbus_error_free (&error);
05547       return FALSE;
05548     }
05549 
05550   return retval;
05551 }
05552 
05567 dbus_bool_t
05568 dbus_connection_try_register_fallback (DBusConnection              *connection,
05569                                        const char                  *path,
05570                                        const DBusObjectPathVTable  *vtable,
05571                                        void                        *user_data,
05572                                        DBusError                   *error)
05573 {
05574   char **decomposed_path;
05575   dbus_bool_t retval;
05576 
05577   _dbus_return_val_if_fail (connection != NULL, FALSE);
05578   _dbus_return_val_if_fail (path != NULL, FALSE);
05579   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05580   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05581 
05582   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05583     return FALSE;
05584 
05585   CONNECTION_LOCK (connection);
05586 
05587   retval = _dbus_object_tree_register (connection->objects,
05588                                        TRUE,
05589                                        (const char **) decomposed_path, vtable,
05590                                        user_data, error);
05591 
05592   CONNECTION_UNLOCK (connection);
05593 
05594   dbus_free_string_array (decomposed_path);
05595 
05596   return retval;
05597 }
05598 
05615 dbus_bool_t
05616 dbus_connection_register_fallback (DBusConnection              *connection,
05617                                    const char                  *path,
05618                                    const DBusObjectPathVTable  *vtable,
05619                                    void                        *user_data)
05620 {
05621   char **decomposed_path;
05622   dbus_bool_t retval;
05623   DBusError error = DBUS_ERROR_INIT;
05624 
05625   _dbus_return_val_if_fail (connection != NULL, FALSE);
05626   _dbus_return_val_if_fail (path != NULL, FALSE);
05627   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05628   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05629 
05630   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05631     return FALSE;
05632 
05633   CONNECTION_LOCK (connection);
05634 
05635   retval = _dbus_object_tree_register (connection->objects,
05636                                        TRUE,
05637                                        (const char **) decomposed_path, vtable,
05638                                        user_data, &error);
05639 
05640   CONNECTION_UNLOCK (connection);
05641 
05642   dbus_free_string_array (decomposed_path);
05643 
05644   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05645     {
05646       _dbus_warn ("%s\n", error.message);
05647       dbus_error_free (&error);
05648       return FALSE;
05649     }
05650 
05651   return retval;
05652 }
05653 
05663 dbus_bool_t
05664 dbus_connection_unregister_object_path (DBusConnection              *connection,
05665                                         const char                  *path)
05666 {
05667   char **decomposed_path;
05668 
05669   _dbus_return_val_if_fail (connection != NULL, FALSE);
05670   _dbus_return_val_if_fail (path != NULL, FALSE);
05671   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05672 
05673   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05674       return FALSE;
05675 
05676   CONNECTION_LOCK (connection);
05677 
05678   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05679 
05680   dbus_free_string_array (decomposed_path);
05681 
05682   return TRUE;
05683 }
05684 
05695 dbus_bool_t
05696 dbus_connection_get_object_path_data (DBusConnection *connection,
05697                                       const char     *path,
05698                                       void          **data_p)
05699 {
05700   char **decomposed_path;
05701 
05702   _dbus_return_val_if_fail (connection != NULL, FALSE);
05703   _dbus_return_val_if_fail (path != NULL, FALSE);
05704   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05705 
05706   *data_p = NULL;
05707   
05708   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05709     return FALSE;
05710   
05711   CONNECTION_LOCK (connection);
05712 
05713   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05714 
05715   CONNECTION_UNLOCK (connection);
05716 
05717   dbus_free_string_array (decomposed_path);
05718 
05719   return TRUE;
05720 }
05721 
05732 dbus_bool_t
05733 dbus_connection_list_registered (DBusConnection              *connection,
05734                                  const char                  *parent_path,
05735                                  char                      ***child_entries)
05736 {
05737   char **decomposed_path;
05738   dbus_bool_t retval;
05739   _dbus_return_val_if_fail (connection != NULL, FALSE);
05740   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05741   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05742   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05743 
05744   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05745     return FALSE;
05746 
05747   CONNECTION_LOCK (connection);
05748 
05749   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05750                                                          (const char **) decomposed_path,
05751                                                          child_entries);
05752   dbus_free_string_array (decomposed_path);
05753 
05754   return retval;
05755 }
05756 
05757 static DBusDataSlotAllocator slot_allocator;
05758 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05759 
05774 dbus_bool_t
05775 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05776 {
05777   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05778                                           &_DBUS_LOCK_NAME (connection_slots),
05779                                           slot_p);
05780 }
05781 
05793 void
05794 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05795 {
05796   _dbus_return_if_fail (*slot_p >= 0);
05797   
05798   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05799 }
05800 
05814 dbus_bool_t
05815 dbus_connection_set_data (DBusConnection   *connection,
05816                           dbus_int32_t      slot,
05817                           void             *data,
05818                           DBusFreeFunction  free_data_func)
05819 {
05820   DBusFreeFunction old_free_func;
05821   void *old_data;
05822   dbus_bool_t retval;
05823 
05824   _dbus_return_val_if_fail (connection != NULL, FALSE);
05825   _dbus_return_val_if_fail (slot >= 0, FALSE);
05826   
05827   CONNECTION_LOCK (connection);
05828 
05829   retval = _dbus_data_slot_list_set (&slot_allocator,
05830                                      &connection->slot_list,
05831                                      slot, data, free_data_func,
05832                                      &old_free_func, &old_data);
05833   
05834   CONNECTION_UNLOCK (connection);
05835 
05836   if (retval)
05837     {
05838       /* Do the actual free outside the connection lock */
05839       if (old_free_func)
05840         (* old_free_func) (old_data);
05841     }
05842 
05843   return retval;
05844 }
05845 
05854 void*
05855 dbus_connection_get_data (DBusConnection   *connection,
05856                           dbus_int32_t      slot)
05857 {
05858   void *res;
05859 
05860   _dbus_return_val_if_fail (connection != NULL, NULL);
05861   
05862   CONNECTION_LOCK (connection);
05863 
05864   res = _dbus_data_slot_list_get (&slot_allocator,
05865                                   &connection->slot_list,
05866                                   slot);
05867   
05868   CONNECTION_UNLOCK (connection);
05869 
05870   return res;
05871 }
05872 
05879 void
05880 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05881 {  
05882   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05883 }
05884 
05893 void
05894 dbus_connection_set_max_message_size (DBusConnection *connection,
05895                                       long            size)
05896 {
05897   _dbus_return_if_fail (connection != NULL);
05898   
05899   CONNECTION_LOCK (connection);
05900   _dbus_transport_set_max_message_size (connection->transport,
05901                                         size);
05902   CONNECTION_UNLOCK (connection);
05903 }
05904 
05911 long
05912 dbus_connection_get_max_message_size (DBusConnection *connection)
05913 {
05914   long res;
05915 
05916   _dbus_return_val_if_fail (connection != NULL, 0);
05917   
05918   CONNECTION_LOCK (connection);
05919   res = _dbus_transport_get_max_message_size (connection->transport);
05920   CONNECTION_UNLOCK (connection);
05921   return res;
05922 }
05923 
05949 void
05950 dbus_connection_set_max_received_size (DBusConnection *connection,
05951                                        long            size)
05952 {
05953   _dbus_return_if_fail (connection != NULL);
05954   
05955   CONNECTION_LOCK (connection);
05956   _dbus_transport_set_max_received_size (connection->transport,
05957                                          size);
05958   CONNECTION_UNLOCK (connection);
05959 }
05960 
05967 long
05968 dbus_connection_get_max_received_size (DBusConnection *connection)
05969 {
05970   long res;
05971 
05972   _dbus_return_val_if_fail (connection != NULL, 0);
05973   
05974   CONNECTION_LOCK (connection);
05975   res = _dbus_transport_get_max_received_size (connection->transport);
05976   CONNECTION_UNLOCK (connection);
05977   return res;
05978 }
05979 
05990 long
05991 dbus_connection_get_outgoing_size (DBusConnection *connection)
05992 {
05993   long res;
05994 
05995   _dbus_return_val_if_fail (connection != NULL, 0);
05996   
05997   CONNECTION_LOCK (connection);
05998   res = _dbus_counter_get_value (connection->outgoing_counter);
05999   CONNECTION_UNLOCK (connection);
06000   return res;
06001 }
06002 

Generated on Sun Feb 20 2011 22:49:18 for D-Bus by  doxygen 1.7.1