Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-list.h"
00033 #include "dbus-hash.h"
00034 #include "dbus-message-internal.h"
00035 #include "dbus-threads.h"
00036 #include "dbus-protocol.h"
00037 #include "dbus-dataslot.h"
00038 #include "dbus-string.h"
00039 #include "dbus-pending-call.h"
00040 #include "dbus-object-tree.h"
00041 #include "dbus-marshal.h"
00042 
00043 #ifdef DBUS_DISABLE_CHECKS
00044 #define TOOK_LOCK_CHECK(connection)
00045 #define RELEASING_LOCK_CHECK(connection)
00046 #define HAVE_LOCK_CHECK(connection)
00047 #else
00048 #define TOOK_LOCK_CHECK(connection) do {                \
00049     _dbus_assert (!(connection)->have_connection_lock); \
00050     (connection)->have_connection_lock = TRUE;          \
00051   } while (0)
00052 #define RELEASING_LOCK_CHECK(connection) do {            \
00053     _dbus_assert ((connection)->have_connection_lock);   \
00054     (connection)->have_connection_lock = FALSE;          \
00055   } while (0)
00056 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00057 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00058 #endif
00059 
00060 #define TRACE_LOCKS 1
00061 
00062 #define CONNECTION_LOCK(connection)   do {                                      \
00063     if (TRACE_LOCKS) { _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME); }   \
00064     dbus_mutex_lock ((connection)->mutex);                                      \
00065     TOOK_LOCK_CHECK (connection);                                               \
00066   } while (0)
00067 
00068 #define CONNECTION_UNLOCK(connection) do {                                              \
00069     if (TRACE_LOCKS) { _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);  }        \
00070     RELEASING_LOCK_CHECK (connection);                                                  \
00071     dbus_mutex_unlock ((connection)->mutex);                                            \
00072   } while (0)
00073 
00074 #define DISPATCH_STATUS_NAME(s)                                            \
00075                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00076                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00077                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00078                       "???")
00079 
00157 typedef struct DBusMessageFilter DBusMessageFilter;
00158 
00162 struct DBusMessageFilter
00163 {
00164   DBusAtomic refcount; 
00165   DBusHandleMessageFunction function; 
00166   void *user_data; 
00167   DBusFreeFunction free_user_data_function; 
00168 };
00169 
00170 
00174 struct DBusPreallocatedSend
00175 {
00176   DBusConnection *connection; 
00177   DBusList *queue_link;       
00178   DBusList *counter_link;     
00179 };
00180 
00181 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00182 
00186 struct DBusConnection
00187 {
00188   DBusAtomic refcount; 
00190   DBusMutex *mutex; 
00192   DBusMutex *dispatch_mutex;     
00193   DBusCondVar *dispatch_cond;    
00194   DBusMutex *io_path_mutex;      
00195   DBusCondVar *io_path_cond;     
00197   DBusList *outgoing_messages; 
00198   DBusList *incoming_messages; 
00200   DBusMessage *message_borrowed; 
00204   int n_outgoing;              
00205   int n_incoming;              
00207   DBusCounter *outgoing_counter; 
00209   DBusTransport *transport;    
00210   DBusWatchList *watches;      
00211   DBusTimeoutList *timeouts;   
00213   DBusList *filter_list;        
00215   DBusDataSlotList slot_list;   
00217   DBusHashTable *pending_replies;  
00219   dbus_uint32_t client_serial;       
00220   DBusList *disconnect_message_link; 
00222   DBusWakeupMainFunction wakeup_main_function; 
00223   void *wakeup_main_data; 
00224   DBusFreeFunction free_wakeup_main_data; 
00226   DBusDispatchStatusFunction dispatch_status_function; 
00227   void *dispatch_status_data; 
00228   DBusFreeFunction free_dispatch_status_data; 
00230   DBusDispatchStatus last_dispatch_status; 
00232   DBusList *link_cache; 
00235   DBusObjectTree *objects; 
00237   unsigned int dispatch_acquired : 1; 
00238   unsigned int io_path_acquired : 1;  
00240   unsigned int exit_on_disconnect : 1; 
00242 #ifndef DBUS_DISABLE_CHECKS
00243   unsigned int have_connection_lock : 1; 
00244 #endif
00245   
00246 #ifndef DBUS_DISABLE_CHECKS
00247   int generation; 
00248 #endif 
00249 };
00250 
00251 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00252 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00253                                                                               DBusDispatchStatus  new_status);
00254 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00255 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00256 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00257 
00258 static DBusMessageFilter *
00259 _dbus_message_filter_ref (DBusMessageFilter *filter)
00260 {
00261   _dbus_assert (filter->refcount.value > 0);
00262   _dbus_atomic_inc (&filter->refcount);
00263 
00264   return filter;
00265 }
00266 
00267 static void
00268 _dbus_message_filter_unref (DBusMessageFilter *filter)
00269 {
00270   _dbus_assert (filter->refcount.value > 0);
00271 
00272   if (_dbus_atomic_dec (&filter->refcount) == 1)
00273     {
00274       if (filter->free_user_data_function)
00275         (* filter->free_user_data_function) (filter->user_data);
00276       
00277       dbus_free (filter);
00278     }
00279 }
00280 
00286 void
00287 _dbus_connection_lock (DBusConnection *connection)
00288 {
00289   CONNECTION_LOCK (connection);
00290 }
00291 
00297 void
00298 _dbus_connection_unlock (DBusConnection *connection)
00299 {
00300   CONNECTION_UNLOCK (connection);
00301 }
00302 
00310 static void
00311 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00312 {
00313   if (connection->wakeup_main_function)
00314     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00315 }
00316 
00317 #ifdef DBUS_BUILD_TESTS
00318 /* For now this function isn't used */
00328 dbus_bool_t
00329 _dbus_connection_queue_received_message (DBusConnection *connection,
00330                                          DBusMessage    *message)
00331 {
00332   DBusList *link;
00333 
00334   link = _dbus_list_alloc_link (message);
00335   if (link == NULL)
00336     return FALSE;
00337 
00338   dbus_message_ref (message);
00339   _dbus_connection_queue_received_message_link (connection, link);
00340 
00341   return TRUE;
00342 }
00343 #endif
00344 
00353 void
00354 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00355                                               DBusList        *link)
00356 {
00357   DBusPendingCall *pending;
00358   dbus_int32_t reply_serial;
00359   DBusMessage *message;
00360   
00361   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00362   
00363   _dbus_list_append_link (&connection->incoming_messages,
00364                           link);
00365   message = link->data;
00366 
00367   /* If this is a reply we're waiting on, remove timeout for it */
00368   reply_serial = dbus_message_get_reply_serial (message);
00369   if (reply_serial != -1)
00370     {
00371       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00372                                              reply_serial);
00373       if (pending != NULL)
00374         {
00375           if (pending->timeout_added)
00376             _dbus_connection_remove_timeout (connection,
00377                                              pending->timeout);
00378 
00379           pending->timeout_added = FALSE;
00380         }
00381     }
00382   
00383   connection->n_incoming += 1;
00384 
00385   _dbus_connection_wakeup_mainloop (connection);
00386   
00387   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00388                  message,
00389                  dbus_message_get_type (message),
00390                  dbus_message_get_path (message),
00391                  dbus_message_get_interface (message) ?
00392                  dbus_message_get_interface (message) :
00393                  "no interface",
00394                  dbus_message_get_member (message) ?
00395                  dbus_message_get_member (message) :
00396                  "no member",
00397                  dbus_message_get_signature (message),
00398                  dbus_message_get_reply_serial (message),
00399                  connection,
00400                  connection->n_incoming);
00401 }
00402 
00413 static void
00414 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00415                                                  DBusList *link)
00416 {
00417   HAVE_LOCK_CHECK (connection);
00418   
00419   _dbus_list_append_link (&connection->incoming_messages, link);
00420 
00421   connection->n_incoming += 1;
00422 
00423   _dbus_connection_wakeup_mainloop (connection);
00424   
00425   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00426                  link->data, connection, connection->n_incoming);
00427 }
00428 
00429 
00437 dbus_bool_t
00438 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00439 {
00440   HAVE_LOCK_CHECK (connection);
00441   return connection->outgoing_messages != NULL;
00442 }
00443 
00450 dbus_bool_t
00451 dbus_connection_has_messages_to_send (DBusConnection *connection)
00452 {
00453   dbus_bool_t v;
00454   
00455   _dbus_return_val_if_fail (connection != NULL, FALSE);
00456 
00457   CONNECTION_LOCK (connection);
00458   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00459   CONNECTION_UNLOCK (connection);
00460 
00461   return v;
00462 }
00463 
00471 DBusMessage*
00472 _dbus_connection_get_message_to_send (DBusConnection *connection)
00473 {
00474   HAVE_LOCK_CHECK (connection);
00475   
00476   return _dbus_list_get_last (&connection->outgoing_messages);
00477 }
00478 
00487 void
00488 _dbus_connection_message_sent (DBusConnection *connection,
00489                                DBusMessage    *message)
00490 {
00491   DBusList *link;
00492 
00493   HAVE_LOCK_CHECK (connection);
00494   
00495   /* This can be called before we even complete authentication, since
00496    * it's called on disconnect to clean up the outgoing queue.
00497    * It's also called as we successfully send each message.
00498    */
00499   
00500   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00501   _dbus_assert (link != NULL);
00502   _dbus_assert (link->data == message);
00503 
00504   /* Save this link in the link cache */
00505   _dbus_list_unlink (&connection->outgoing_messages,
00506                      link);
00507   _dbus_list_prepend_link (&connection->link_cache, link);
00508   
00509   connection->n_outgoing -= 1;
00510 
00511   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00512                  message,
00513                  dbus_message_get_type (message),
00514                  dbus_message_get_path (message),
00515                  dbus_message_get_interface (message) ?
00516                  dbus_message_get_interface (message) :
00517                  "no interface",
00518                  dbus_message_get_member (message) ?
00519                  dbus_message_get_member (message) :
00520                  "no member",
00521                  dbus_message_get_signature (message),
00522                  connection, connection->n_outgoing);
00523 
00524   /* Save this link in the link cache also */
00525   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00526                                      &link);
00527   _dbus_list_prepend_link (&connection->link_cache, link);
00528   
00529   dbus_message_unref (message);
00530 }
00531 
00532 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00533                                                   DBusWatch     *watch);
00534 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00535                                                   DBusWatch     *watch);
00536 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00537                                                   DBusWatch     *watch,
00538                                                   dbus_bool_t    enabled);
00539 
00540 static dbus_bool_t
00541 protected_change_watch (DBusConnection         *connection,
00542                         DBusWatch              *watch,
00543                         DBusWatchAddFunction    add_function,
00544                         DBusWatchRemoveFunction remove_function,
00545                         DBusWatchToggleFunction toggle_function,
00546                         dbus_bool_t             enabled)
00547 {
00548   DBusWatchList *watches;
00549   dbus_bool_t retval;
00550   
00551   HAVE_LOCK_CHECK (connection);
00552 
00553   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00554    * drop lock and call out" one; but it has to be propagated up through all callers
00555    */
00556   
00557   watches = connection->watches;
00558   if (watches)
00559     {
00560       connection->watches = NULL;
00561       _dbus_connection_ref_unlocked (connection);
00562       CONNECTION_UNLOCK (connection);
00563 
00564       if (add_function)
00565         retval = (* add_function) (watches, watch);
00566       else if (remove_function)
00567         {
00568           retval = TRUE;
00569           (* remove_function) (watches, watch);
00570         }
00571       else
00572         {
00573           retval = TRUE;
00574           (* toggle_function) (watches, watch, enabled);
00575         }
00576       
00577       CONNECTION_LOCK (connection);
00578       connection->watches = watches;
00579       _dbus_connection_unref_unlocked (connection);
00580 
00581       return retval;
00582     }
00583   else
00584     return FALSE;
00585 }
00586      
00587 
00598 dbus_bool_t
00599 _dbus_connection_add_watch (DBusConnection *connection,
00600                             DBusWatch      *watch)
00601 {
00602   return protected_change_watch (connection, watch,
00603                                  _dbus_watch_list_add_watch,
00604                                  NULL, NULL, FALSE);
00605 }
00606 
00615 void
00616 _dbus_connection_remove_watch (DBusConnection *connection,
00617                                DBusWatch      *watch)
00618 {
00619   protected_change_watch (connection, watch,
00620                           NULL,
00621                           _dbus_watch_list_remove_watch,
00622                           NULL, FALSE);
00623 }
00624 
00635 void
00636 _dbus_connection_toggle_watch (DBusConnection *connection,
00637                                DBusWatch      *watch,
00638                                dbus_bool_t     enabled)
00639 {
00640   _dbus_assert (watch != NULL);
00641 
00642   protected_change_watch (connection, watch,
00643                           NULL, NULL,
00644                           _dbus_watch_list_toggle_watch,
00645                           enabled);
00646 }
00647 
00648 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00649                                                    DBusTimeout     *timeout);
00650 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00651                                                    DBusTimeout     *timeout);
00652 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00653                                                    DBusTimeout     *timeout,
00654                                                    dbus_bool_t      enabled);
00655 
00656 static dbus_bool_t
00657 protected_change_timeout (DBusConnection           *connection,
00658                           DBusTimeout              *timeout,
00659                           DBusTimeoutAddFunction    add_function,
00660                           DBusTimeoutRemoveFunction remove_function,
00661                           DBusTimeoutToggleFunction toggle_function,
00662                           dbus_bool_t               enabled)
00663 {
00664   DBusTimeoutList *timeouts;
00665   dbus_bool_t retval;
00666   
00667   HAVE_LOCK_CHECK (connection);
00668 
00669   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00670    * drop lock and call out" one; but it has to be propagated up through all callers
00671    */
00672   
00673   timeouts = connection->timeouts;
00674   if (timeouts)
00675     {
00676       connection->timeouts = NULL;
00677       _dbus_connection_ref_unlocked (connection);
00678       CONNECTION_UNLOCK (connection);
00679 
00680       if (add_function)
00681         retval = (* add_function) (timeouts, timeout);
00682       else if (remove_function)
00683         {
00684           retval = TRUE;
00685           (* remove_function) (timeouts, timeout);
00686         }
00687       else
00688         {
00689           retval = TRUE;
00690           (* toggle_function) (timeouts, timeout, enabled);
00691         }
00692       
00693       CONNECTION_LOCK (connection);
00694       connection->timeouts = timeouts;
00695       _dbus_connection_unref_unlocked (connection);
00696 
00697       return retval;
00698     }
00699   else
00700     return FALSE;
00701 }
00702 
00714 dbus_bool_t
00715 _dbus_connection_add_timeout (DBusConnection *connection,
00716                               DBusTimeout    *timeout)
00717 {
00718   return protected_change_timeout (connection, timeout,
00719                                    _dbus_timeout_list_add_timeout,
00720                                    NULL, NULL, FALSE);
00721 }
00722 
00731 void
00732 _dbus_connection_remove_timeout (DBusConnection *connection,
00733                                  DBusTimeout    *timeout)
00734 {
00735   protected_change_timeout (connection, timeout,
00736                             NULL,
00737                             _dbus_timeout_list_remove_timeout,
00738                             NULL, FALSE);
00739 }
00740 
00750 void
00751 _dbus_connection_toggle_timeout (DBusConnection   *connection,
00752                                  DBusTimeout      *timeout,
00753                                  dbus_bool_t       enabled)
00754 {
00755   protected_change_timeout (connection, timeout,
00756                             NULL, NULL,
00757                             _dbus_timeout_list_toggle_timeout,
00758                             enabled);
00759 }
00760 
00761 static dbus_bool_t
00762 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00763                                                DBusPendingCall *pending)
00764 {
00765   HAVE_LOCK_CHECK (connection);
00766   
00767   _dbus_assert (pending->reply_serial != 0);
00768 
00769   if (!_dbus_connection_add_timeout (connection, pending->timeout))
00770     return FALSE;
00771   
00772   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00773                                     pending->reply_serial,
00774                                     pending))
00775     {
00776       _dbus_connection_remove_timeout (connection, pending->timeout);
00777 
00778       HAVE_LOCK_CHECK (connection);
00779       return FALSE;
00780     }
00781   
00782   pending->timeout_added = TRUE;
00783   pending->connection = connection;
00784 
00785   dbus_pending_call_ref (pending);
00786 
00787   HAVE_LOCK_CHECK (connection);
00788   
00789   return TRUE;
00790 }
00791 
00792 static void
00793 free_pending_call_on_hash_removal (void *data)
00794 {
00795   DBusPendingCall *pending;
00796   
00797   if (data == NULL)
00798     return;
00799 
00800   pending = data;
00801 
00802   if (pending->connection)
00803     {
00804       if (pending->timeout_added)
00805         {
00806           _dbus_connection_remove_timeout (pending->connection,
00807                                            pending->timeout);
00808           pending->timeout_added = FALSE;
00809         }
00810 
00811       pending->connection = NULL;
00812       
00813       dbus_pending_call_unref (pending);
00814     }
00815 }
00816 
00817 static void
00818 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00819                                                DBusPendingCall *pending)
00820 {
00821   /* Can't have a destroy notifier on the pending call if we're going to do this */
00822 
00823   dbus_pending_call_ref (pending);
00824   _dbus_hash_table_remove_int (connection->pending_replies,
00825                                pending->reply_serial);
00826   _dbus_assert (pending->connection == NULL);
00827   dbus_pending_call_unref (pending);
00828 }
00829 
00830 static void
00831 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00832                                                  DBusPendingCall *pending)
00833 {
00834   /* The idea here is to avoid finalizing the pending call
00835    * with the lock held, since there's a destroy notifier
00836    * in pending call that goes out to application code.
00837    */
00838   dbus_pending_call_ref (pending);
00839   _dbus_hash_table_remove_int (connection->pending_replies,
00840                                pending->reply_serial);
00841   _dbus_assert (pending->connection == NULL);
00842   CONNECTION_UNLOCK (connection);
00843   dbus_pending_call_unref (pending);
00844 }
00845 
00854 void
00855 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00856                                       DBusPendingCall *pending)
00857 {
00858   CONNECTION_LOCK (connection);
00859   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00860 }
00861 
00870 void
00871 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00872                                         DBusMessage     *message)
00873 {
00874   if (message == NULL)
00875     {
00876       message = pending->timeout_link->data;
00877       _dbus_list_clear (&pending->timeout_link);
00878     }
00879   else
00880     dbus_message_ref (message);
00881 
00882   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
00883                  message,
00884                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00885                  "method return" :
00886                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00887                  "error" : "other type",
00888                  pending->reply_serial);
00889   
00890   _dbus_assert (pending->reply == NULL);
00891   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00892   pending->reply = message;
00893   
00894   dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
00895   _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00896   
00897   /* Must be called unlocked since it invokes app callback */
00898   _dbus_pending_call_notify (pending);
00899   dbus_pending_call_unref (pending);
00900 }
00901 
00911 static dbus_bool_t
00912 _dbus_connection_acquire_io_path (DBusConnection *connection,
00913                                   int timeout_milliseconds)
00914 {
00915   dbus_bool_t we_acquired;
00916   
00917   HAVE_LOCK_CHECK (connection);
00918 
00919   /* We don't want the connection to vanish */
00920   _dbus_connection_ref_unlocked (connection);
00921 
00922   /* We will only touch io_path_acquired which is protected by our mutex */
00923   CONNECTION_UNLOCK (connection);
00924   
00925   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00926   dbus_mutex_lock (connection->io_path_mutex);
00927 
00928   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00929                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00930 
00931   we_acquired = FALSE;
00932   
00933   if (connection->io_path_acquired)
00934     {
00935       if (timeout_milliseconds != -1)
00936         {
00937           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00938                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
00939           dbus_condvar_wait_timeout (connection->io_path_cond,
00940                                      connection->io_path_mutex,
00941                                      timeout_milliseconds);
00942         }
00943       else
00944         {
00945           while (connection->io_path_acquired)
00946             {
00947               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00948               dbus_condvar_wait (connection->io_path_cond, connection->io_path_mutex);
00949             }
00950         }
00951     }
00952   
00953   if (!connection->io_path_acquired)
00954     {
00955       we_acquired = TRUE;
00956       connection->io_path_acquired = TRUE;
00957     }
00958   
00959   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00960                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00961 
00962   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00963   dbus_mutex_unlock (connection->io_path_mutex);
00964 
00965   CONNECTION_LOCK (connection);
00966   
00967   HAVE_LOCK_CHECK (connection);
00968 
00969   _dbus_connection_unref_unlocked (connection);
00970   
00971   return we_acquired;
00972 }
00973 
00981 static void
00982 _dbus_connection_release_io_path (DBusConnection *connection)
00983 {
00984   HAVE_LOCK_CHECK (connection);
00985   
00986   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00987   dbus_mutex_lock (connection->io_path_mutex);
00988   
00989   _dbus_assert (connection->io_path_acquired);
00990 
00991   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
00992                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
00993   
00994   connection->io_path_acquired = FALSE;
00995   dbus_condvar_wake_one (connection->io_path_cond);
00996 
00997   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00998   dbus_mutex_unlock (connection->io_path_mutex);
00999 }
01000 
01029 void
01030 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01031                                         unsigned int    flags,
01032                                         int             timeout_milliseconds)
01033 {
01034   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01035   
01036   HAVE_LOCK_CHECK (connection);
01037   
01038   if (connection->n_outgoing == 0)
01039     flags &= ~DBUS_ITERATION_DO_WRITING;
01040 
01041   if (_dbus_connection_acquire_io_path (connection,
01042                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01043     {
01044       HAVE_LOCK_CHECK (connection);
01045       
01046       _dbus_transport_do_iteration (connection->transport,
01047                                     flags, timeout_milliseconds);
01048       _dbus_connection_release_io_path (connection);
01049     }
01050 
01051   HAVE_LOCK_CHECK (connection);
01052 
01053   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01054 }
01055 
01065 DBusConnection*
01066 _dbus_connection_new_for_transport (DBusTransport *transport)
01067 {
01068   DBusConnection *connection;
01069   DBusWatchList *watch_list;
01070   DBusTimeoutList *timeout_list;
01071   DBusHashTable *pending_replies;
01072   DBusMutex *mutex;
01073   DBusMutex *io_path_mutex;
01074   DBusMutex *dispatch_mutex;
01075   DBusCondVar *message_returned_cond;
01076   DBusCondVar *dispatch_cond;
01077   DBusCondVar *io_path_cond;
01078   DBusList *disconnect_link;
01079   DBusMessage *disconnect_message;
01080   DBusCounter *outgoing_counter;
01081   DBusObjectTree *objects;
01082   
01083   watch_list = NULL;
01084   connection = NULL;
01085   pending_replies = NULL;
01086   timeout_list = NULL;
01087   mutex = NULL;
01088   io_path_mutex = NULL;
01089   dispatch_mutex = NULL;
01090   message_returned_cond = NULL;
01091   dispatch_cond = NULL;
01092   io_path_cond = NULL;
01093   disconnect_link = NULL;
01094   disconnect_message = NULL;
01095   outgoing_counter = NULL;
01096   objects = NULL;
01097   
01098   watch_list = _dbus_watch_list_new ();
01099   if (watch_list == NULL)
01100     goto error;
01101 
01102   timeout_list = _dbus_timeout_list_new ();
01103   if (timeout_list == NULL)
01104     goto error;  
01105 
01106   pending_replies =
01107     _dbus_hash_table_new (DBUS_HASH_INT,
01108                           NULL,
01109                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01110   if (pending_replies == NULL)
01111     goto error;
01112   
01113   connection = dbus_new0 (DBusConnection, 1);
01114   if (connection == NULL)
01115     goto error;
01116 
01117   mutex = dbus_mutex_new ();
01118   if (mutex == NULL)
01119     goto error;
01120 
01121   io_path_mutex = dbus_mutex_new ();
01122   if (io_path_mutex == NULL)
01123     goto error;
01124 
01125   dispatch_mutex = dbus_mutex_new ();
01126   if (dispatch_mutex == NULL)
01127     goto error;
01128   
01129   message_returned_cond = dbus_condvar_new ();
01130   if (message_returned_cond == NULL)
01131     goto error;
01132   
01133   dispatch_cond = dbus_condvar_new ();
01134   if (dispatch_cond == NULL)
01135     goto error;
01136   
01137   io_path_cond = dbus_condvar_new ();
01138   if (io_path_cond == NULL)
01139     goto error;
01140 
01141   disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL,
01142                                                 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
01143                                                 "Disconnected");
01144   
01145   if (disconnect_message == NULL)
01146     goto error;
01147 
01148   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01149   if (disconnect_link == NULL)
01150     goto error;
01151 
01152   outgoing_counter = _dbus_counter_new ();
01153   if (outgoing_counter == NULL)
01154     goto error;
01155 
01156   objects = _dbus_object_tree_new (connection);
01157   if (objects == NULL)
01158     goto error;
01159   
01160   if (_dbus_modify_sigpipe)
01161     _dbus_disable_sigpipe ();
01162   
01163   connection->refcount.value = 1;
01164   connection->mutex = mutex;
01165   connection->dispatch_cond = dispatch_cond;
01166   connection->dispatch_mutex = dispatch_mutex;
01167   connection->io_path_cond = io_path_cond;
01168   connection->io_path_mutex = io_path_mutex;
01169   connection->transport = transport;
01170   connection->watches = watch_list;
01171   connection->timeouts = timeout_list;
01172   connection->pending_replies = pending_replies;
01173   connection->outgoing_counter = outgoing_counter;
01174   connection->filter_list = NULL;
01175   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01176   connection->objects = objects;
01177   connection->exit_on_disconnect = FALSE;
01178 #ifndef DBUS_DISABLE_CHECKS
01179   connection->generation = _dbus_current_generation;
01180 #endif
01181   
01182   _dbus_data_slot_list_init (&connection->slot_list);
01183 
01184   connection->client_serial = 1;
01185 
01186   connection->disconnect_message_link = disconnect_link;
01187 
01188   CONNECTION_LOCK (connection);
01189   
01190   if (!_dbus_transport_set_connection (transport, connection))
01191     goto error;
01192 
01193   _dbus_transport_ref (transport);
01194 
01195   CONNECTION_UNLOCK (connection);
01196   
01197   return connection;
01198   
01199  error:
01200   if (disconnect_message != NULL)
01201     dbus_message_unref (disconnect_message);
01202   
01203   if (disconnect_link != NULL)
01204     _dbus_list_free_link (disconnect_link);
01205   
01206   if (io_path_cond != NULL)
01207     dbus_condvar_free (io_path_cond);
01208   
01209   if (dispatch_cond != NULL)
01210     dbus_condvar_free (dispatch_cond);
01211   
01212   if (message_returned_cond != NULL)
01213     dbus_condvar_free (message_returned_cond);
01214   
01215   if (mutex != NULL)
01216     dbus_mutex_free (mutex);
01217 
01218   if (io_path_mutex != NULL)
01219     dbus_mutex_free (io_path_mutex);
01220 
01221   if (dispatch_mutex != NULL)
01222     dbus_mutex_free (dispatch_mutex);
01223   
01224   if (connection != NULL)
01225     dbus_free (connection);
01226 
01227   if (pending_replies)
01228     _dbus_hash_table_unref (pending_replies);
01229   
01230   if (watch_list)
01231     _dbus_watch_list_free (watch_list);
01232 
01233   if (timeout_list)
01234     _dbus_timeout_list_free (timeout_list);
01235 
01236   if (outgoing_counter)
01237     _dbus_counter_unref (outgoing_counter);
01238 
01239   if (objects)
01240     _dbus_object_tree_unref (objects);
01241   
01242   return NULL;
01243 }
01244 
01252 DBusConnection *
01253 _dbus_connection_ref_unlocked (DBusConnection *connection)
01254 {  
01255   _dbus_assert (connection != NULL);
01256   _dbus_assert (connection->generation == _dbus_current_generation);
01257 
01258   HAVE_LOCK_CHECK (connection);
01259   
01260 #ifdef DBUS_HAVE_ATOMIC_INT
01261   _dbus_atomic_inc (&connection->refcount);
01262 #else
01263   _dbus_assert (connection->refcount.value > 0);
01264   connection->refcount.value += 1;
01265 #endif
01266 
01267   return connection;
01268 }
01269 
01276 void
01277 _dbus_connection_unref_unlocked (DBusConnection *connection)
01278 {
01279   dbus_bool_t last_unref;
01280 
01281   HAVE_LOCK_CHECK (connection);
01282   
01283   _dbus_assert (connection != NULL);
01284 
01285   /* The connection lock is better than the global
01286    * lock in the atomic increment fallback
01287    */
01288   
01289 #ifdef DBUS_HAVE_ATOMIC_INT
01290   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01291 #else
01292   _dbus_assert (connection->refcount.value > 0);
01293 
01294   connection->refcount.value -= 1;
01295   last_unref = (connection->refcount.value == 0);  
01296 #if 0
01297   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01298 #endif
01299 #endif
01300   
01301   if (last_unref)
01302     _dbus_connection_last_unref (connection);
01303 }
01304 
01305 static dbus_uint32_t
01306 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01307 {
01308   int serial;
01309 
01310   serial = connection->client_serial++;
01311 
01312   if (connection->client_serial < 0)
01313     connection->client_serial = 1;
01314   
01315   return serial;
01316 }
01317 
01331 dbus_bool_t
01332 _dbus_connection_handle_watch (DBusWatch                   *watch,
01333                                unsigned int                 condition,
01334                                void                        *data)
01335 {
01336   DBusConnection *connection;
01337   dbus_bool_t retval;
01338   DBusDispatchStatus status;
01339 
01340   connection = data;
01341 
01342   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01343   
01344   CONNECTION_LOCK (connection);
01345   _dbus_connection_acquire_io_path (connection, -1);
01346   HAVE_LOCK_CHECK (connection);
01347   retval = _dbus_transport_handle_watch (connection->transport,
01348                                          watch, condition);
01349 
01350   _dbus_connection_release_io_path (connection);
01351 
01352   HAVE_LOCK_CHECK (connection);
01353 
01354   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01355   
01356   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01357 
01358   /* this calls out to user code */
01359   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01360 
01361   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01362   
01363   return retval;
01364 }
01365 
01390 DBusConnection*
01391 dbus_connection_open (const char     *address,
01392                       DBusError      *error)
01393 {
01394   DBusConnection *connection;
01395   DBusTransport *transport;
01396 
01397   _dbus_return_val_if_fail (address != NULL, NULL);
01398   _dbus_return_val_if_error_is_set (error, NULL);
01399   
01400   transport = _dbus_transport_open (address, error);
01401   if (transport == NULL)
01402     {
01403       _DBUS_ASSERT_ERROR_IS_SET (error);
01404       return NULL;
01405     }
01406   
01407   connection = _dbus_connection_new_for_transport (transport);
01408 
01409   _dbus_transport_unref (transport);
01410   
01411   if (connection == NULL)
01412     {
01413       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01414       return NULL;
01415     }
01416 
01417 #ifndef DBUS_DISABLE_CHECKS
01418   _dbus_assert (!connection->have_connection_lock);
01419 #endif
01420   return connection;
01421 }
01422 
01429 DBusConnection *
01430 dbus_connection_ref (DBusConnection *connection)
01431 {
01432   _dbus_return_val_if_fail (connection != NULL, NULL);
01433   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01434   
01435   /* The connection lock is better than the global
01436    * lock in the atomic increment fallback
01437    */
01438   
01439 #ifdef DBUS_HAVE_ATOMIC_INT
01440   _dbus_atomic_inc (&connection->refcount);
01441 #else
01442   CONNECTION_LOCK (connection);
01443   _dbus_assert (connection->refcount.value > 0);
01444 
01445   connection->refcount.value += 1;
01446   CONNECTION_UNLOCK (connection);
01447 #endif
01448 
01449   return connection;
01450 }
01451 
01452 static void
01453 free_outgoing_message (void *element,
01454                        void *data)
01455 {
01456   DBusMessage *message = element;
01457   DBusConnection *connection = data;
01458 
01459   _dbus_message_remove_size_counter (message,
01460                                      connection->outgoing_counter,
01461                                      NULL);
01462   dbus_message_unref (message);
01463 }
01464 
01465 /* This is run without the mutex held, but after the last reference
01466  * to the connection has been dropped we should have no thread-related
01467  * problems
01468  */
01469 static void
01470 _dbus_connection_last_unref (DBusConnection *connection)
01471 {
01472   DBusList *link;
01473 
01474   _dbus_verbose ("Finalizing connection %p\n", connection);
01475   
01476   _dbus_assert (connection->refcount.value == 0);
01477   
01478   /* You have to disconnect the connection before unref:ing it. Otherwise
01479    * you won't get the disconnected message.
01480    */
01481   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01482 
01483   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01484   _dbus_object_tree_free_all_unlocked (connection->objects);
01485   
01486   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01487   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01488   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01489   
01490   _dbus_watch_list_free (connection->watches);
01491   connection->watches = NULL;
01492   
01493   _dbus_timeout_list_free (connection->timeouts);
01494   connection->timeouts = NULL;
01495 
01496   _dbus_data_slot_list_free (&connection->slot_list);
01497   
01498   link = _dbus_list_get_first_link (&connection->filter_list);
01499   while (link != NULL)
01500     {
01501       DBusMessageFilter *filter = link->data;
01502       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01503 
01504       filter->function = NULL;
01505       _dbus_message_filter_unref (filter); /* calls app callback */
01506       link->data = NULL;
01507       
01508       link = next;
01509     }
01510   _dbus_list_clear (&connection->filter_list);
01511   
01512   /* ---- Done with stuff that invokes application callbacks */
01513 
01514   _dbus_object_tree_unref (connection->objects);  
01515 
01516   _dbus_hash_table_unref (connection->pending_replies);
01517   connection->pending_replies = NULL;
01518   
01519   _dbus_list_clear (&connection->filter_list);
01520   
01521   _dbus_list_foreach (&connection->outgoing_messages,
01522                       free_outgoing_message,
01523                       connection);
01524   _dbus_list_clear (&connection->outgoing_messages);
01525   
01526   _dbus_list_foreach (&connection->incoming_messages,
01527                       (DBusForeachFunction) dbus_message_unref,
01528                       NULL);
01529   _dbus_list_clear (&connection->incoming_messages);
01530 
01531   _dbus_counter_unref (connection->outgoing_counter);
01532   
01533   _dbus_transport_unref (connection->transport);
01534 
01535   if (connection->disconnect_message_link)
01536     {
01537       DBusMessage *message = connection->disconnect_message_link->data;
01538       dbus_message_unref (message);
01539       _dbus_list_free_link (connection->disconnect_message_link);
01540     }
01541 
01542   _dbus_list_clear (&connection->link_cache);
01543   
01544   dbus_condvar_free (connection->dispatch_cond);
01545   dbus_condvar_free (connection->io_path_cond);
01546 
01547   dbus_mutex_free (connection->io_path_mutex);
01548   dbus_mutex_free (connection->dispatch_mutex);
01549 
01550   dbus_mutex_free (connection->mutex);
01551   
01552   dbus_free (connection);
01553 }
01554 
01566 void
01567 dbus_connection_unref (DBusConnection *connection)
01568 {
01569   dbus_bool_t last_unref;
01570 
01571   _dbus_return_if_fail (connection != NULL);
01572   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01573   
01574   /* The connection lock is better than the global
01575    * lock in the atomic increment fallback
01576    */
01577   
01578 #ifdef DBUS_HAVE_ATOMIC_INT
01579   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01580 #else
01581   CONNECTION_LOCK (connection);
01582   
01583   _dbus_assert (connection->refcount.value > 0);
01584 
01585   connection->refcount.value -= 1;
01586   last_unref = (connection->refcount.value == 0);
01587 
01588 #if 0
01589   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01590 #endif
01591   
01592   CONNECTION_UNLOCK (connection);
01593 #endif
01594   
01595   if (last_unref)
01596     _dbus_connection_last_unref (connection);
01597 }
01598 
01612 void
01613 dbus_connection_disconnect (DBusConnection *connection)
01614 {
01615   DBusDispatchStatus status;
01616   
01617   _dbus_return_if_fail (connection != NULL);
01618   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01619 
01620   _dbus_verbose ("Disconnecting %p\n", connection);
01621   
01622   CONNECTION_LOCK (connection);
01623   _dbus_transport_disconnect (connection->transport);
01624 
01625   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01626   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01627 
01628   /* this calls out to user code */
01629   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01630 }
01631 
01632 static dbus_bool_t
01633 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01634 {
01635   HAVE_LOCK_CHECK (connection);
01636   return _dbus_transport_get_is_connected (connection->transport);
01637 }
01638 
01649 dbus_bool_t
01650 dbus_connection_get_is_connected (DBusConnection *connection)
01651 {
01652   dbus_bool_t res;
01653 
01654   _dbus_return_val_if_fail (connection != NULL, FALSE);
01655   
01656   CONNECTION_LOCK (connection);
01657   res = _dbus_connection_get_is_connected_unlocked (connection);
01658   CONNECTION_UNLOCK (connection);
01659   
01660   return res;
01661 }
01662 
01671 dbus_bool_t
01672 dbus_connection_get_is_authenticated (DBusConnection *connection)
01673 {
01674   dbus_bool_t res;
01675 
01676   _dbus_return_val_if_fail (connection != NULL, FALSE);
01677   
01678   CONNECTION_LOCK (connection);
01679   res = _dbus_transport_get_is_authenticated (connection->transport);
01680   CONNECTION_UNLOCK (connection);
01681   
01682   return res;
01683 }
01684 
01698 void
01699 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
01700                                         dbus_bool_t     exit_on_disconnect)
01701 {
01702   _dbus_return_if_fail (connection != NULL);
01703 
01704   CONNECTION_LOCK (connection);
01705   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
01706   CONNECTION_UNLOCK (connection);
01707 }
01708 
01709 static DBusPreallocatedSend*
01710 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01711 {
01712   DBusPreallocatedSend *preallocated;
01713 
01714   HAVE_LOCK_CHECK (connection);
01715   
01716   _dbus_assert (connection != NULL);
01717   
01718   preallocated = dbus_new (DBusPreallocatedSend, 1);
01719   if (preallocated == NULL)
01720     return NULL;
01721 
01722   if (connection->link_cache != NULL)
01723     {
01724       preallocated->queue_link =
01725         _dbus_list_pop_first_link (&connection->link_cache);
01726       preallocated->queue_link->data = NULL;
01727     }
01728   else
01729     {
01730       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01731       if (preallocated->queue_link == NULL)
01732         goto failed_0;
01733     }
01734   
01735   if (connection->link_cache != NULL)
01736     {
01737       preallocated->counter_link =
01738         _dbus_list_pop_first_link (&connection->link_cache);
01739       preallocated->counter_link->data = connection->outgoing_counter;
01740     }
01741   else
01742     {
01743       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01744       if (preallocated->counter_link == NULL)
01745         goto failed_1;
01746     }
01747 
01748   _dbus_counter_ref (preallocated->counter_link->data);
01749 
01750   preallocated->connection = connection;
01751   
01752   return preallocated;
01753   
01754  failed_1:
01755   _dbus_list_free_link (preallocated->queue_link);
01756  failed_0:
01757   dbus_free (preallocated);
01758   
01759   return NULL;
01760 }
01761 
01771 DBusPreallocatedSend*
01772 dbus_connection_preallocate_send (DBusConnection *connection)
01773 {
01774   DBusPreallocatedSend *preallocated;
01775 
01776   _dbus_return_val_if_fail (connection != NULL, NULL);
01777 
01778   CONNECTION_LOCK (connection);
01779   
01780   preallocated =
01781     _dbus_connection_preallocate_send_unlocked (connection);
01782 
01783   CONNECTION_UNLOCK (connection);
01784 
01785   return preallocated;
01786 }
01787 
01797 void
01798 dbus_connection_free_preallocated_send (DBusConnection       *connection,
01799                                         DBusPreallocatedSend *preallocated)
01800 {
01801   _dbus_return_if_fail (connection != NULL);
01802   _dbus_return_if_fail (preallocated != NULL);  
01803   _dbus_return_if_fail (connection == preallocated->connection);
01804 
01805   _dbus_list_free_link (preallocated->queue_link);
01806   _dbus_counter_unref (preallocated->counter_link->data);
01807   _dbus_list_free_link (preallocated->counter_link);
01808   dbus_free (preallocated);
01809 }
01810 
01811 /* Called with lock held, does not update dispatch status */
01812 static void
01813 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01814                                                        DBusPreallocatedSend *preallocated,
01815                                                        DBusMessage          *message,
01816                                                        dbus_uint32_t        *client_serial)
01817 {
01818   dbus_uint32_t serial;
01819   const char *sig;
01820 
01821   preallocated->queue_link->data = message;
01822   _dbus_list_prepend_link (&connection->outgoing_messages,
01823                            preallocated->queue_link);
01824 
01825   _dbus_message_add_size_counter_link (message,
01826                                        preallocated->counter_link);
01827 
01828   dbus_free (preallocated);
01829   preallocated = NULL;
01830   
01831   dbus_message_ref (message);
01832   
01833   connection->n_outgoing += 1;
01834 
01835   sig = dbus_message_get_signature (message);
01836   
01837   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01838                  message,
01839                  dbus_message_get_type (message),
01840                  dbus_message_get_path (message),
01841                  dbus_message_get_interface (message) ?
01842                  dbus_message_get_interface (message) :
01843                  "no interface",
01844                  dbus_message_get_member (message) ?
01845                  dbus_message_get_member (message) :
01846                  "no member",
01847                  sig,
01848                  dbus_message_get_destination (message) ?
01849                  dbus_message_get_destination (message) :
01850                  "null",
01851                  connection,
01852                  connection->n_outgoing);
01853 
01854   if (dbus_message_get_serial (message) == 0)
01855     {
01856       serial = _dbus_connection_get_next_client_serial (connection);
01857       _dbus_message_set_serial (message, serial);
01858       if (client_serial)
01859         *client_serial = serial;
01860     }
01861   else
01862     {
01863       if (client_serial)
01864         *client_serial = dbus_message_get_serial (message);
01865     }
01866 
01867   _dbus_verbose ("Message %p serial is %u\n",
01868                  message, dbus_message_get_serial (message));
01869   
01870   _dbus_message_lock (message);
01871 
01872   /* Now we need to run an iteration to hopefully just write the messages
01873    * out immediately, and otherwise get them queued up
01874    */
01875   _dbus_connection_do_iteration_unlocked (connection,
01876                                           DBUS_ITERATION_DO_WRITING,
01877                                           -1);
01878 
01879   /* If stuff is still queued up, be sure we wake up the main loop */
01880   if (connection->n_outgoing > 0)
01881     _dbus_connection_wakeup_mainloop (connection);
01882 }
01883 
01884 static void
01885 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
01886                                                DBusPreallocatedSend *preallocated,
01887                                                DBusMessage          *message,
01888                                                dbus_uint32_t        *client_serial)
01889 {
01890   DBusDispatchStatus status;
01891 
01892   HAVE_LOCK_CHECK (connection);
01893   
01894   _dbus_connection_send_preallocated_unlocked_no_update (connection,
01895                                                          preallocated,
01896                                                          message, client_serial);
01897 
01898   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01899   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01900 
01901   /* this calls out to user code */
01902   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01903 }
01904 
01917 void
01918 dbus_connection_send_preallocated (DBusConnection       *connection,
01919                                    DBusPreallocatedSend *preallocated,
01920                                    DBusMessage          *message,
01921                                    dbus_uint32_t        *client_serial)
01922 {
01923   _dbus_return_if_fail (connection != NULL);
01924   _dbus_return_if_fail (preallocated != NULL);
01925   _dbus_return_if_fail (message != NULL);
01926   _dbus_return_if_fail (preallocated->connection == connection);
01927   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
01928                         (dbus_message_get_interface (message) != NULL &&
01929                          dbus_message_get_member (message) != NULL));
01930   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
01931                         (dbus_message_get_interface (message) != NULL &&
01932                          dbus_message_get_member (message) != NULL));
01933   
01934   CONNECTION_LOCK (connection);
01935   _dbus_connection_send_preallocated_and_unlock (connection,
01936                                                  preallocated,
01937                                                  message, client_serial);
01938 }
01939 
01940 static dbus_bool_t
01941 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
01942                                           DBusMessage    *message,
01943                                           dbus_uint32_t  *client_serial)
01944 {
01945   DBusPreallocatedSend *preallocated;
01946 
01947   _dbus_assert (connection != NULL);
01948   _dbus_assert (message != NULL);
01949   
01950   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01951   if (preallocated == NULL)
01952     return FALSE;
01953 
01954   _dbus_connection_send_preallocated_unlocked_no_update (connection,
01955                                                          preallocated,
01956                                                          message,
01957                                                          client_serial);
01958   return TRUE;
01959 }
01960 
01961 dbus_bool_t
01962 _dbus_connection_send_and_unlock (DBusConnection *connection,
01963                                   DBusMessage    *message,
01964                                   dbus_uint32_t  *client_serial)
01965 {
01966   DBusPreallocatedSend *preallocated;
01967 
01968   _dbus_assert (connection != NULL);
01969   _dbus_assert (message != NULL);
01970   
01971   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01972   if (preallocated == NULL)
01973     {
01974       CONNECTION_UNLOCK (connection);
01975       return FALSE;
01976     }
01977 
01978   _dbus_connection_send_preallocated_and_unlock (connection,
01979                                                  preallocated,
01980                                                  message,
01981                                                  client_serial);
01982   return TRUE;
01983 }
01984 
02003 dbus_bool_t
02004 dbus_connection_send (DBusConnection *connection,
02005                       DBusMessage    *message,
02006                       dbus_uint32_t  *client_serial)
02007 {
02008   _dbus_return_val_if_fail (connection != NULL, FALSE);
02009   _dbus_return_val_if_fail (message != NULL, FALSE);
02010 
02011   CONNECTION_LOCK (connection);
02012 
02013   return _dbus_connection_send_and_unlock (connection,
02014                                            message,
02015                                            client_serial);
02016 }
02017 
02018 static dbus_bool_t
02019 reply_handler_timeout (void *data)
02020 {
02021   DBusConnection *connection;
02022   DBusDispatchStatus status;
02023   DBusPendingCall *pending = data;
02024 
02025   connection = pending->connection;
02026   
02027   CONNECTION_LOCK (connection);
02028   if (pending->timeout_link)
02029     {
02030       _dbus_connection_queue_synthesized_message_link (connection,
02031                                                        pending->timeout_link);
02032       pending->timeout_link = NULL;
02033     }
02034 
02035   _dbus_connection_remove_timeout (connection,
02036                                    pending->timeout);
02037   pending->timeout_added = FALSE;
02038 
02039   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02040   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02041 
02042   /* Unlocks, and calls out to user code */
02043   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02044   
02045   return TRUE;
02046 }
02047 
02085 dbus_bool_t
02086 dbus_connection_send_with_reply (DBusConnection     *connection,
02087                                  DBusMessage        *message,
02088                                  DBusPendingCall   **pending_return,
02089                                  int                 timeout_milliseconds)
02090 {
02091   DBusPendingCall *pending;
02092   DBusMessage *reply;
02093   DBusList *reply_link;
02094   dbus_int32_t serial = -1;
02095   DBusDispatchStatus status;
02096 
02097   _dbus_return_val_if_fail (connection != NULL, FALSE);
02098   _dbus_return_val_if_fail (message != NULL, FALSE);
02099   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02100 
02101   if (pending_return)
02102     *pending_return = NULL;
02103   
02104   pending = _dbus_pending_call_new (connection,
02105                                     timeout_milliseconds,
02106                                     reply_handler_timeout);
02107 
02108   if (pending == NULL)
02109     return FALSE;
02110 
02111   CONNECTION_LOCK (connection);
02112   
02113   /* Assign a serial to the message */
02114   if (dbus_message_get_serial (message) == 0)
02115     {
02116       serial = _dbus_connection_get_next_client_serial (connection);
02117       _dbus_message_set_serial (message, serial);
02118     }
02119 
02120   pending->reply_serial = serial;
02121 
02122   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02123                                   "No reply within specified time");
02124   if (reply == NULL)
02125     goto error;
02126 
02127   reply_link = _dbus_list_alloc_link (reply);
02128   if (reply_link == NULL)
02129     {
02130       CONNECTION_UNLOCK (connection);
02131       dbus_message_unref (reply);
02132       goto error_unlocked;
02133     }
02134 
02135   pending->timeout_link = reply_link;
02136 
02137   /* Insert the serial in the pending replies hash;
02138    * hash takes a refcount on DBusPendingCall.
02139    * Also, add the timeout.
02140    */
02141   if (!_dbus_connection_attach_pending_call_unlocked (connection,
02142                                                       pending))
02143     goto error;
02144 
02145   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02146     {
02147       _dbus_connection_detach_pending_call_and_unlock (connection,
02148                                                        pending);
02149       goto error_unlocked;
02150     }
02151 
02152   if (pending_return)
02153     *pending_return = pending;
02154   else
02155     {
02156       _dbus_connection_detach_pending_call_unlocked (connection, pending);
02157       dbus_pending_call_unref (pending);
02158     }
02159 
02160   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02161   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02162 
02163   /* this calls out to user code */
02164   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02165 
02166   return TRUE;
02167 
02168  error:
02169   CONNECTION_UNLOCK (connection);
02170  error_unlocked:
02171   dbus_pending_call_unref (pending);
02172   return FALSE;
02173 }
02174 
02175 /* This is slightly strange since we can pop a message here without
02176  * the dispatch lock.
02177  */
02178 static DBusMessage*
02179 check_for_reply_unlocked (DBusConnection *connection,
02180                           dbus_uint32_t   client_serial)
02181 {
02182   DBusList *link;
02183 
02184   HAVE_LOCK_CHECK (connection);
02185   
02186   link = _dbus_list_get_first_link (&connection->incoming_messages);
02187 
02188   while (link != NULL)
02189     {
02190       DBusMessage *reply = link->data;
02191 
02192       if (dbus_message_get_reply_serial (reply) == client_serial)
02193         {
02194           _dbus_list_remove_link (&connection->incoming_messages, link);
02195           connection->n_incoming  -= 1;
02196           return reply;
02197         }
02198       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02199     }
02200 
02201   return NULL;
02202 }
02203 
02218 void
02219 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02220 {
02221   long start_tv_sec, start_tv_usec;
02222   long end_tv_sec, end_tv_usec;
02223   long tv_sec, tv_usec;
02224   DBusDispatchStatus status;
02225   DBusConnection *connection;
02226   dbus_uint32_t client_serial;
02227   int timeout_milliseconds;
02228 
02229   _dbus_assert (pending != NULL);
02230 
02231   if (dbus_pending_call_get_completed (pending))
02232     return;
02233 
02234   if (pending->connection == NULL)
02235     return; /* call already detached */
02236 
02237   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02238   
02239   connection = pending->connection;
02240   client_serial = pending->reply_serial;
02241 
02242   /* note that timeout_milliseconds is limited to a smallish value
02243    * in _dbus_pending_call_new() so overflows aren't possible
02244    * below
02245    */
02246   timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02247 
02248   /* Flush message queue */
02249   dbus_connection_flush (connection);
02250 
02251   CONNECTION_LOCK (connection);
02252 
02253   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02254   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02255   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02256   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02257   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02258 
02259   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n",
02260                  timeout_milliseconds,
02261                  client_serial,
02262                  start_tv_sec, start_tv_usec,
02263                  end_tv_sec, end_tv_usec);
02264 
02265   /* Now we wait... */
02266   /* always block at least once as we know we don't have the reply yet */
02267   _dbus_connection_do_iteration_unlocked (connection,
02268                                           DBUS_ITERATION_DO_READING |
02269                                           DBUS_ITERATION_BLOCK,
02270                                           timeout_milliseconds);
02271 
02272  recheck_status:
02273 
02274   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02275   
02276   HAVE_LOCK_CHECK (connection);
02277   
02278   /* queue messages and get status */
02279 
02280   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02281 
02282   /* the get_completed() is in case a dispatch() while we were blocking
02283    * got the reply instead of us.
02284    */
02285   if (dbus_pending_call_get_completed (pending))
02286     {
02287       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02288       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02289       dbus_pending_call_unref (pending);
02290       return;
02291     }
02292   
02293   if (status == DBUS_DISPATCH_DATA_REMAINS)
02294     {
02295       DBusMessage *reply;
02296       
02297       reply = check_for_reply_unlocked (connection, client_serial);
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           _dbus_pending_call_complete_and_unlock (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;
02313         }
02314     }
02315   
02316   _dbus_get_current_time (&tv_sec, &tv_usec);
02317   
02318   if (!_dbus_connection_get_is_connected_unlocked (connection))
02319     {
02320       /* FIXME send a "DBUS_ERROR_DISCONNECTED" instead, just to help
02321        * programmers understand what went wrong since the timeout is
02322        * confusing
02323        */
02324       
02325       _dbus_pending_call_complete_and_unlock (pending, NULL);
02326       dbus_pending_call_unref (pending);
02327       return;
02328     }
02329   else if (tv_sec < start_tv_sec)
02330     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02331   else if (connection->disconnect_message_link == NULL)
02332     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02333   else if (tv_sec < end_tv_sec ||
02334            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02335     {
02336       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02337         (end_tv_usec - tv_usec) / 1000;
02338       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02339       _dbus_assert (timeout_milliseconds >= 0);
02340       
02341       if (status == DBUS_DISPATCH_NEED_MEMORY)
02342         {
02343           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02344            * we may already have a reply in the buffer and just can't process
02345            * it.
02346            */
02347           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02348           
02349           if (timeout_milliseconds < 100)
02350             ; /* just busy loop */
02351           else if (timeout_milliseconds <= 1000)
02352             _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02353           else
02354             _dbus_sleep_milliseconds (1000);
02355         }
02356       else
02357         {          
02358           /* block again, we don't have the reply buffered yet. */
02359           _dbus_connection_do_iteration_unlocked (connection,
02360                                                   DBUS_ITERATION_DO_READING |
02361                                                   DBUS_ITERATION_BLOCK,
02362                                                   timeout_milliseconds);
02363         }
02364 
02365       goto recheck_status;
02366     }
02367 
02368   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02369                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02370 
02371   _dbus_assert (!dbus_pending_call_get_completed (pending));
02372   
02373   /* unlock and call user code */
02374   _dbus_pending_call_complete_and_unlock (pending, NULL);
02375 
02376   /* update user code on dispatch status */
02377   CONNECTION_LOCK (connection);
02378   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02379   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02380   dbus_pending_call_unref (pending);
02381 }
02382 
02405 DBusMessage*
02406 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
02407                                            DBusMessage        *message,
02408                                            int                 timeout_milliseconds,
02409                                            DBusError          *error)
02410 {
02411   DBusMessage *reply;
02412   DBusPendingCall *pending;
02413   
02414   _dbus_return_val_if_fail (connection != NULL, NULL);
02415   _dbus_return_val_if_fail (message != NULL, NULL);
02416   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);  
02417   _dbus_return_val_if_error_is_set (error, NULL);
02418   
02419   if (!dbus_connection_send_with_reply (connection, message,
02420                                         &pending, timeout_milliseconds))
02421     {
02422       _DBUS_SET_OOM (error);
02423       return NULL;
02424     }
02425 
02426   _dbus_assert (pending != NULL);
02427   
02428   dbus_pending_call_block (pending);
02429 
02430   reply = dbus_pending_call_steal_reply (pending);
02431   dbus_pending_call_unref (pending);
02432 
02433   /* call_complete_and_unlock() called from pending_call_block() should
02434    * always fill this in.
02435    */
02436   _dbus_assert (reply != NULL);
02437   
02438    if (dbus_set_error_from_message (error, reply))
02439     {
02440       dbus_message_unref (reply);
02441       return NULL;
02442     }
02443   else
02444     return reply;
02445 }
02446 
02452 void
02453 dbus_connection_flush (DBusConnection *connection)
02454 {
02455   /* We have to specify DBUS_ITERATION_DO_READING here because
02456    * otherwise we could have two apps deadlock if they are both doing
02457    * a flush(), and the kernel buffers fill up. This could change the
02458    * dispatch status.
02459    */
02460   DBusDispatchStatus status;
02461 
02462   _dbus_return_if_fail (connection != NULL);
02463   
02464   CONNECTION_LOCK (connection);
02465   while (connection->n_outgoing > 0 &&
02466          _dbus_connection_get_is_connected_unlocked (connection))
02467     {
02468       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02469       HAVE_LOCK_CHECK (connection);
02470       _dbus_connection_do_iteration_unlocked (connection,
02471                                               DBUS_ITERATION_DO_READING |
02472                                               DBUS_ITERATION_DO_WRITING |
02473                                               DBUS_ITERATION_BLOCK,
02474                                               -1);
02475     }
02476 
02477   HAVE_LOCK_CHECK (connection);
02478   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02479   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02480 
02481   HAVE_LOCK_CHECK (connection);
02482   /* Unlocks and calls out to user code */
02483   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02484 
02485   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02486 }
02487 
02507 DBusMessage*
02508 dbus_connection_borrow_message (DBusConnection *connection)
02509 {
02510   DBusDispatchStatus status;
02511   DBusMessage *message;
02512 
02513   _dbus_return_val_if_fail (connection != NULL, NULL);
02514 
02515   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02516   
02517   /* this is called for the side effect that it queues
02518    * up any messages from the transport
02519    */
02520   status = dbus_connection_get_dispatch_status (connection);
02521   if (status != DBUS_DISPATCH_DATA_REMAINS)
02522     return NULL;
02523   
02524   CONNECTION_LOCK (connection);
02525 
02526   _dbus_connection_acquire_dispatch (connection);
02527 
02528   /* While a message is outstanding, the dispatch lock is held */
02529   _dbus_assert (connection->message_borrowed == NULL);
02530 
02531   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
02532   
02533   message = connection->message_borrowed;
02534 
02535   /* Note that we KEEP the dispatch lock until the message is returned */
02536   if (message == NULL)
02537     _dbus_connection_release_dispatch (connection);
02538 
02539   CONNECTION_UNLOCK (connection);
02540   
02541   return message;
02542 }
02543 
02552 void
02553 dbus_connection_return_message (DBusConnection *connection,
02554                                 DBusMessage    *message)
02555 {
02556   _dbus_return_if_fail (connection != NULL);
02557   _dbus_return_if_fail (message != NULL);
02558   _dbus_return_if_fail (message == connection->message_borrowed);
02559   _dbus_return_if_fail (connection->dispatch_acquired);
02560   
02561   CONNECTION_LOCK (connection);
02562   
02563   _dbus_assert (message == connection->message_borrowed);
02564   
02565   connection->message_borrowed = NULL;
02566 
02567   _dbus_connection_release_dispatch (connection);
02568   
02569   CONNECTION_UNLOCK (connection);
02570 }
02571 
02581 void
02582 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02583                                         DBusMessage    *message)
02584 {
02585   DBusMessage *pop_message;
02586 
02587   _dbus_return_if_fail (connection != NULL);
02588   _dbus_return_if_fail (message != NULL);
02589   _dbus_return_if_fail (message == connection->message_borrowed);
02590   _dbus_return_if_fail (connection->dispatch_acquired);
02591   
02592   CONNECTION_LOCK (connection);
02593  
02594   _dbus_assert (message == connection->message_borrowed);
02595 
02596   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
02597   _dbus_assert (message == pop_message);
02598   
02599   connection->n_incoming -= 1;
02600  
02601   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
02602                  message, connection->n_incoming);
02603  
02604   connection->message_borrowed = NULL;
02605 
02606   _dbus_connection_release_dispatch (connection);
02607   
02608   CONNECTION_UNLOCK (connection);
02609 }
02610 
02611 /* See dbus_connection_pop_message, but requires the caller to own
02612  * the lock before calling. May drop the lock while running.
02613  */
02614 static DBusList*
02615 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
02616 {
02617   HAVE_LOCK_CHECK (connection);
02618   
02619   _dbus_assert (connection->message_borrowed == NULL);
02620   
02621   if (connection->n_incoming > 0)
02622     {
02623       DBusList *link;
02624 
02625       link = _dbus_list_pop_first_link (&connection->incoming_messages);
02626       connection->n_incoming -= 1;
02627 
02628       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
02629                      link->data,
02630                      dbus_message_get_type (link->data),
02631                      dbus_message_get_path (link->data), 
02632                      dbus_message_get_interface (link->data) ?
02633                      dbus_message_get_interface (link->data) :
02634                      "no interface",
02635                      dbus_message_get_member (link->data) ?
02636                      dbus_message_get_member (link->data) :
02637                      "no member",
02638                      dbus_message_get_signature (link->data),
02639                      connection, connection->n_incoming);
02640 
02641       return link;
02642     }
02643   else
02644     return NULL;
02645 }
02646 
02647 /* See dbus_connection_pop_message, but requires the caller to own
02648  * the lock before calling. May drop the lock while running.
02649  */
02650 static DBusMessage*
02651 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
02652 {
02653   DBusList *link;
02654 
02655   HAVE_LOCK_CHECK (connection);
02656   
02657   link = _dbus_connection_pop_message_link_unlocked (connection);
02658 
02659   if (link != NULL)
02660     {
02661       DBusMessage *message;
02662       
02663       message = link->data;
02664       
02665       _dbus_list_free_link (link);
02666       
02667       return message;
02668     }
02669   else
02670     return NULL;
02671 }
02672 
02673 static void
02674 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
02675                                                 DBusList       *message_link)
02676 {
02677   HAVE_LOCK_CHECK (connection);
02678   
02679   _dbus_assert (message_link != NULL);
02680   /* You can't borrow a message while a link is outstanding */
02681   _dbus_assert (connection->message_borrowed == NULL);
02682   /* We had to have the dispatch lock across the pop/putback */
02683   _dbus_assert (connection->dispatch_acquired);
02684 
02685   _dbus_list_prepend_link (&connection->incoming_messages,
02686                            message_link);
02687   connection->n_incoming += 1;
02688 
02689   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
02690                  message_link->data,
02691                  dbus_message_get_type (message_link->data),
02692                  dbus_message_get_interface (message_link->data) ?
02693                  dbus_message_get_interface (message_link->data) :
02694                  "no interface",
02695                  dbus_message_get_member (message_link->data) ?
02696                  dbus_message_get_member (message_link->data) :
02697                  "no member",
02698                  dbus_message_get_signature (message_link->data),
02699                  connection, connection->n_incoming);
02700 }
02701 
02721 DBusMessage*
02722 dbus_connection_pop_message (DBusConnection *connection)
02723 {
02724   DBusMessage *message;
02725   DBusDispatchStatus status;
02726 
02727   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02728   
02729   /* this is called for the side effect that it queues
02730    * up any messages from the transport
02731    */
02732   status = dbus_connection_get_dispatch_status (connection);
02733   if (status != DBUS_DISPATCH_DATA_REMAINS)
02734     return NULL;
02735   
02736   CONNECTION_LOCK (connection);
02737   _dbus_connection_acquire_dispatch (connection);
02738   HAVE_LOCK_CHECK (connection);
02739   
02740   message = _dbus_connection_pop_message_unlocked (connection);
02741 
02742   _dbus_verbose ("Returning popped message %p\n", message);    
02743 
02744   _dbus_connection_release_dispatch (connection);
02745   CONNECTION_UNLOCK (connection);
02746   
02747   return message;
02748 }
02749 
02757 static void
02758 _dbus_connection_acquire_dispatch (DBusConnection *connection)
02759 {
02760   HAVE_LOCK_CHECK (connection);
02761 
02762   _dbus_connection_ref_unlocked (connection);
02763   CONNECTION_UNLOCK (connection);
02764   
02765   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
02766   dbus_mutex_lock (connection->dispatch_mutex);
02767 
02768   while (connection->dispatch_acquired)
02769     {
02770       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
02771       dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
02772     }
02773   
02774   _dbus_assert (!connection->dispatch_acquired);
02775 
02776   connection->dispatch_acquired = TRUE;
02777 
02778   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
02779   dbus_mutex_unlock (connection->dispatch_mutex);
02780   
02781   CONNECTION_LOCK (connection);
02782   _dbus_connection_unref_unlocked (connection);
02783 }
02784 
02792 static void
02793 _dbus_connection_release_dispatch (DBusConnection *connection)
02794 {
02795   HAVE_LOCK_CHECK (connection);
02796   
02797   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
02798   dbus_mutex_lock (connection->dispatch_mutex);
02799   
02800   _dbus_assert (connection->dispatch_acquired);
02801 
02802   connection->dispatch_acquired = FALSE;
02803   dbus_condvar_wake_one (connection->dispatch_cond);
02804 
02805   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
02806   dbus_mutex_unlock (connection->dispatch_mutex);
02807 }
02808 
02809 static void
02810 _dbus_connection_failed_pop (DBusConnection *connection,
02811                              DBusList       *message_link)
02812 {
02813   _dbus_list_prepend_link (&connection->incoming_messages,
02814                            message_link);
02815   connection->n_incoming += 1;
02816 }
02817 
02818 static DBusDispatchStatus
02819 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
02820 {
02821   HAVE_LOCK_CHECK (connection);
02822   
02823   if (connection->n_incoming > 0)
02824     return DBUS_DISPATCH_DATA_REMAINS;
02825   else if (!_dbus_transport_queue_messages (connection->transport))
02826     return DBUS_DISPATCH_NEED_MEMORY;
02827   else
02828     {
02829       DBusDispatchStatus status;
02830       dbus_bool_t is_connected;
02831       
02832       status = _dbus_transport_get_dispatch_status (connection->transport);
02833       is_connected = _dbus_transport_get_is_connected (connection->transport);
02834 
02835       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
02836                      DISPATCH_STATUS_NAME (status), is_connected);
02837       
02838       if (!is_connected)
02839         {
02840           if (status == DBUS_DISPATCH_COMPLETE &&
02841               connection->disconnect_message_link)
02842             {
02843               _dbus_verbose ("Sending disconnect message from %s\n",
02844                              _DBUS_FUNCTION_NAME);
02845                              
02846               /* We haven't sent the disconnect message already,
02847                * and all real messages have been queued up.
02848                */
02849               _dbus_connection_queue_synthesized_message_link (connection,
02850                                                                connection->disconnect_message_link);
02851               connection->disconnect_message_link = NULL;
02852             }
02853 
02854           /* Dump the outgoing queue, we aren't going to be able to
02855            * send it now, and we'd like accessors like
02856            * dbus_connection_get_outgoing_size() to be accurate.
02857            */
02858           if (connection->n_outgoing > 0)
02859             {
02860               DBusList *link;
02861               
02862               _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
02863                              connection->n_outgoing);
02864               
02865               while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
02866                 {
02867                   _dbus_connection_message_sent (connection, link->data);
02868                 }
02869             }
02870         }
02871       
02872       if (status != DBUS_DISPATCH_COMPLETE)
02873         return status;
02874       else if (connection->n_incoming > 0)
02875         return DBUS_DISPATCH_DATA_REMAINS;
02876       else
02877         return DBUS_DISPATCH_COMPLETE;
02878     }
02879 }
02880 
02881 static void
02882 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
02883                                                     DBusDispatchStatus new_status)
02884 {
02885   dbus_bool_t changed;
02886   DBusDispatchStatusFunction function;
02887   void *data;
02888 
02889   HAVE_LOCK_CHECK (connection);
02890 
02891   _dbus_connection_ref_unlocked (connection);
02892 
02893   changed = new_status != connection->last_dispatch_status;
02894 
02895   connection->last_dispatch_status = new_status;
02896 
02897   function = connection->dispatch_status_function;
02898   data = connection->dispatch_status_data;
02899 
02900   /* We drop the lock */
02901   CONNECTION_UNLOCK (connection);
02902   
02903   if (changed && function)
02904     {
02905       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
02906                      connection, new_status,
02907                      DISPATCH_STATUS_NAME (new_status));
02908       (* function) (connection, new_status, data);      
02909     }
02910   
02911   dbus_connection_unref (connection);
02912 }
02913 
02922 DBusDispatchStatus
02923 dbus_connection_get_dispatch_status (DBusConnection *connection)
02924 {
02925   DBusDispatchStatus status;
02926 
02927   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02928 
02929   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02930   
02931   CONNECTION_LOCK (connection);
02932 
02933   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02934   
02935   CONNECTION_UNLOCK (connection);
02936 
02937   return status;
02938 }
02939 
02963 DBusDispatchStatus
02964 dbus_connection_dispatch (DBusConnection *connection)
02965 {
02966   DBusMessage *message;
02967   DBusList *link, *filter_list_copy, *message_link;
02968   DBusHandlerResult result;
02969   DBusPendingCall *pending;
02970   dbus_int32_t reply_serial;
02971   DBusDispatchStatus status;
02972 
02973   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02974 
02975   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
02976   
02977   CONNECTION_LOCK (connection);
02978   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02979   if (status != DBUS_DISPATCH_DATA_REMAINS)
02980     {
02981       /* unlocks and calls out to user code */
02982       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02983       return status;
02984     }
02985   
02986   /* We need to ref the connection since the callback could potentially
02987    * drop the last ref to it
02988    */
02989   _dbus_connection_ref_unlocked (connection);
02990 
02991   _dbus_connection_acquire_dispatch (connection);
02992   HAVE_LOCK_CHECK (connection);
02993 
02994   message_link = _dbus_connection_pop_message_link_unlocked (connection);
02995   if (message_link == NULL)
02996     {
02997       /* another thread dispatched our stuff */
02998 
02999       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03000       
03001       _dbus_connection_release_dispatch (connection);
03002 
03003       status = _dbus_connection_get_dispatch_status_unlocked (connection);
03004 
03005       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03006       
03007       dbus_connection_unref (connection);
03008       
03009       return status;
03010     }
03011 
03012   message = message_link->data;
03013 
03014   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03015                  message,
03016                  dbus_message_get_type (message),
03017                  dbus_message_get_interface (message) ?
03018                  dbus_message_get_interface (message) :
03019                  "no interface",
03020                  dbus_message_get_member (message) ?
03021                  dbus_message_get_member (message) :
03022                  "no member",
03023                  dbus_message_get_signature (message));
03024 
03025   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03026   
03027   /* Pending call handling must be first, because if you do
03028    * dbus_connection_send_with_reply_and_block() or
03029    * dbus_pending_call_block() then no handlers/filters will be run on
03030    * the reply. We want consistent semantics in the case where we
03031    * dbus_connection_dispatch() the reply.
03032    */
03033   
03034   reply_serial = dbus_message_get_reply_serial (message);
03035   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03036                                          reply_serial);
03037   if (pending)
03038     {
03039       _dbus_verbose ("Dispatching a pending reply\n");
03040       _dbus_pending_call_complete_and_unlock (pending, message);
03041       pending = NULL; /* it's probably unref'd */
03042       
03043       CONNECTION_LOCK (connection);
03044       _dbus_verbose ("pending call completed in dispatch\n");
03045       result = DBUS_HANDLER_RESULT_HANDLED;
03046       goto out;
03047     }
03048   
03049   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03050     {
03051       _dbus_connection_release_dispatch (connection);
03052       HAVE_LOCK_CHECK (connection);
03053       
03054       _dbus_connection_failed_pop (connection, message_link);
03055 
03056       /* unlocks and calls user code */
03057       _dbus_connection_update_dispatch_status_and_unlock (connection,
03058                                                           DBUS_DISPATCH_NEED_MEMORY);
03059 
03060       if (pending)
03061         dbus_pending_call_unref (pending);
03062       dbus_connection_unref (connection);
03063       
03064       return DBUS_DISPATCH_NEED_MEMORY;
03065     }
03066   
03067   _dbus_list_foreach (&filter_list_copy,
03068                       (DBusForeachFunction)_dbus_message_filter_ref,
03069                       NULL);
03070 
03071   /* We're still protected from dispatch() reentrancy here
03072    * since we acquired the dispatcher
03073    */
03074   CONNECTION_UNLOCK (connection);
03075   
03076   link = _dbus_list_get_first_link (&filter_list_copy);
03077   while (link != NULL)
03078     {
03079       DBusMessageFilter *filter = link->data;
03080       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03081 
03082       _dbus_verbose ("  running filter on message %p\n", message);
03083       result = (* filter->function) (connection, message, filter->user_data);
03084 
03085       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03086         break;
03087 
03088       link = next;
03089     }
03090 
03091   _dbus_list_foreach (&filter_list_copy,
03092                       (DBusForeachFunction)_dbus_message_filter_unref,
03093                       NULL);
03094   _dbus_list_clear (&filter_list_copy);
03095   
03096   CONNECTION_LOCK (connection);
03097 
03098   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03099     {
03100       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03101       goto out;
03102     }
03103   else if (result == DBUS_HANDLER_RESULT_HANDLED)
03104     {
03105       _dbus_verbose ("filter handled message in dispatch\n");
03106       goto out;
03107     }
03108 
03109   /* We're still protected from dispatch() reentrancy here
03110    * since we acquired the dispatcher
03111    */
03112   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
03113                  message,
03114                  dbus_message_get_type (message),
03115                  dbus_message_get_interface (message) ?
03116                  dbus_message_get_interface (message) :
03117                  "no interface",
03118                  dbus_message_get_member (message) ?
03119                  dbus_message_get_member (message) :
03120                  "no member",
03121                  dbus_message_get_signature (message));
03122 
03123   HAVE_LOCK_CHECK (connection);
03124   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03125                                                   message);
03126   
03127   CONNECTION_LOCK (connection);
03128 
03129   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03130     {
03131       _dbus_verbose ("object tree handled message in dispatch\n");
03132       goto out;
03133     }
03134 
03135   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03136     {
03137       DBusMessage *reply;
03138       DBusString str;
03139       DBusPreallocatedSend *preallocated;
03140 
03141       _dbus_verbose ("  sending error %s\n",
03142                      DBUS_ERROR_UNKNOWN_METHOD);
03143       
03144       if (!_dbus_string_init (&str))
03145         {
03146           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03147           _dbus_verbose ("no memory for error string in dispatch\n");
03148           goto out;
03149         }
03150               
03151       if (!_dbus_string_append_printf (&str,
03152                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03153                                        dbus_message_get_member (message),
03154                                        dbus_message_get_signature (message),
03155                                        dbus_message_get_interface (message)))
03156         {
03157           _dbus_string_free (&str);
03158           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03159           _dbus_verbose ("no memory for error string in dispatch\n");
03160           goto out;
03161         }
03162       
03163       reply = dbus_message_new_error (message,
03164                                       DBUS_ERROR_UNKNOWN_METHOD,
03165                                       _dbus_string_get_const_data (&str));
03166       _dbus_string_free (&str);
03167 
03168       if (reply == NULL)
03169         {
03170           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03171           _dbus_verbose ("no memory for error reply in dispatch\n");
03172           goto out;
03173         }
03174       
03175       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03176 
03177       if (preallocated == NULL)
03178         {
03179           dbus_message_unref (reply);
03180           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03181           _dbus_verbose ("no memory for error send in dispatch\n");
03182           goto out;
03183         }
03184 
03185       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03186                                                              reply, NULL);
03187 
03188       dbus_message_unref (reply);
03189       
03190       result = DBUS_HANDLER_RESULT_HANDLED;
03191     }
03192   
03193   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03194                  dbus_message_get_type (message),
03195                  dbus_message_get_interface (message) ?
03196                  dbus_message_get_interface (message) :
03197                  "no interface",
03198                  dbus_message_get_member (message) ?
03199                  dbus_message_get_member (message) :
03200                  "no member",
03201                  dbus_message_get_signature (message),
03202                  connection);
03203   
03204  out:
03205   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03206     {
03207       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03208       
03209       /* Put message back, and we'll start over.
03210        * Yes this means handlers must be idempotent if they
03211        * don't return HANDLED; c'est la vie.
03212        */
03213       _dbus_connection_putback_message_link_unlocked (connection,
03214                                                       message_link);
03215     }
03216   else
03217     {
03218       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03219       
03220       if (connection->exit_on_disconnect &&
03221           dbus_message_is_signal (message,
03222                                   DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
03223                                   "Disconnected"))
03224         {
03225           _dbus_verbose ("Exiting on Disconnected signal\n");
03226           CONNECTION_UNLOCK (connection);
03227           _dbus_exit (1);
03228           _dbus_assert_not_reached ("Call to exit() returned");
03229         }
03230       
03231       _dbus_list_free_link (message_link);
03232       dbus_message_unref (message); /* don't want the message to count in max message limits
03233                                      * in computing dispatch status below
03234                                      */
03235     }
03236   
03237   _dbus_connection_release_dispatch (connection);
03238   HAVE_LOCK_CHECK (connection);
03239 
03240   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03241   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03242 
03243   /* unlocks and calls user code */
03244   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03245   
03246   dbus_connection_unref (connection);
03247   
03248   return status;
03249 }
03250 
03309 dbus_bool_t
03310 dbus_connection_set_watch_functions (DBusConnection              *connection,
03311                                      DBusAddWatchFunction         add_function,
03312                                      DBusRemoveWatchFunction      remove_function,
03313                                      DBusWatchToggledFunction     toggled_function,
03314                                      void                        *data,
03315                                      DBusFreeFunction             free_data_function)
03316 {
03317   dbus_bool_t retval;
03318   DBusWatchList *watches;
03319 
03320   _dbus_return_val_if_fail (connection != NULL, FALSE);
03321   
03322   CONNECTION_LOCK (connection);
03323 
03324 #ifndef DBUS_DISABLE_CHECKS
03325   if (connection->watches == NULL)
03326     {
03327       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03328                   _DBUS_FUNCTION_NAME);
03329       return FALSE;
03330     }
03331 #endif
03332   
03333   /* ref connection for slightly better reentrancy */
03334   _dbus_connection_ref_unlocked (connection);
03335 
03336   /* This can call back into user code, and we need to drop the
03337    * connection lock when it does. This is kind of a lame
03338    * way to do it.
03339    */
03340   watches = connection->watches;
03341   connection->watches = NULL;
03342   CONNECTION_UNLOCK (connection);
03343 
03344   retval = _dbus_watch_list_set_functions (watches,
03345                                            add_function, remove_function,
03346                                            toggled_function,
03347                                            data, free_data_function);
03348   CONNECTION_LOCK (connection);
03349   connection->watches = watches;
03350   
03351   CONNECTION_UNLOCK (connection);
03352   /* drop our paranoid refcount */
03353   dbus_connection_unref (connection);
03354   
03355   return retval;
03356 }
03357 
03391 dbus_bool_t
03392 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
03393                                          DBusAddTimeoutFunction     add_function,
03394                                          DBusRemoveTimeoutFunction  remove_function,
03395                                          DBusTimeoutToggledFunction toggled_function,
03396                                          void                      *data,
03397                                          DBusFreeFunction           free_data_function)
03398 {
03399   dbus_bool_t retval;
03400   DBusTimeoutList *timeouts;
03401 
03402   _dbus_return_val_if_fail (connection != NULL, FALSE);
03403   
03404   CONNECTION_LOCK (connection);
03405 
03406 #ifndef DBUS_DISABLE_CHECKS
03407   if (connection->timeouts == NULL)
03408     {
03409       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03410                   _DBUS_FUNCTION_NAME);
03411       return FALSE;
03412     }
03413 #endif
03414   
03415   /* ref connection for slightly better reentrancy */
03416   _dbus_connection_ref_unlocked (connection);
03417 
03418   timeouts = connection->timeouts;
03419   connection->timeouts = NULL;
03420   CONNECTION_UNLOCK (connection);
03421   
03422   retval = _dbus_timeout_list_set_functions (timeouts,
03423                                              add_function, remove_function,
03424                                              toggled_function,
03425                                              data, free_data_function);
03426   CONNECTION_LOCK (connection);
03427   connection->timeouts = timeouts;
03428   
03429   CONNECTION_UNLOCK (connection);
03430   /* drop our paranoid refcount */
03431   dbus_connection_unref (connection);
03432 
03433   return retval;
03434 }
03435 
03450 void
03451 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
03452                                           DBusWakeupMainFunction     wakeup_main_function,
03453                                           void                      *data,
03454                                           DBusFreeFunction           free_data_function)
03455 {
03456   void *old_data;
03457   DBusFreeFunction old_free_data;
03458 
03459   _dbus_return_if_fail (connection != NULL);
03460   
03461   CONNECTION_LOCK (connection);
03462   old_data = connection->wakeup_main_data;
03463   old_free_data = connection->free_wakeup_main_data;
03464 
03465   connection->wakeup_main_function = wakeup_main_function;
03466   connection->wakeup_main_data = data;
03467   connection->free_wakeup_main_data = free_data_function;
03468   
03469   CONNECTION_UNLOCK (connection);
03470 
03471   /* Callback outside the lock */
03472   if (old_free_data)
03473     (*old_free_data) (old_data);
03474 }
03475 
03492 void
03493 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
03494                                               DBusDispatchStatusFunction  function,
03495                                               void                       *data,
03496                                               DBusFreeFunction            free_data_function)
03497 {
03498   void *old_data;
03499   DBusFreeFunction old_free_data;
03500 
03501   _dbus_return_if_fail (connection != NULL);
03502   
03503   CONNECTION_LOCK (connection);
03504   old_data = connection->dispatch_status_data;
03505   old_free_data = connection->free_dispatch_status_data;
03506 
03507   connection->dispatch_status_function = function;
03508   connection->dispatch_status_data = data;
03509   connection->free_dispatch_status_data = free_data_function;
03510   
03511   CONNECTION_UNLOCK (connection);
03512 
03513   /* Callback outside the lock */
03514   if (old_free_data)
03515     (*old_free_data) (old_data);
03516 }
03517 
03530 dbus_bool_t
03531 dbus_connection_get_unix_fd (DBusConnection *connection,
03532                              int            *fd)
03533 {
03534   dbus_bool_t retval;
03535 
03536   _dbus_return_val_if_fail (connection != NULL, FALSE);
03537   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
03538   
03539   CONNECTION_LOCK (connection);
03540   
03541   retval = _dbus_transport_get_unix_fd (connection->transport,
03542                                         fd);
03543 
03544   CONNECTION_UNLOCK (connection);
03545 
03546   return retval;
03547 }
03548 
03560 dbus_bool_t
03561 dbus_connection_get_unix_user (DBusConnection *connection,
03562                                unsigned long  *uid)
03563 {
03564   dbus_bool_t result;
03565 
03566   _dbus_return_val_if_fail (connection != NULL, FALSE);
03567   _dbus_return_val_if_fail (uid != NULL, FALSE);
03568   
03569   CONNECTION_LOCK (connection);
03570 
03571   if (!_dbus_transport_get_is_authenticated (connection->transport))
03572     result = FALSE;
03573   else
03574     result = _dbus_transport_get_unix_user (connection->transport,
03575                                             uid);
03576   CONNECTION_UNLOCK (connection);
03577 
03578   return result;
03579 }
03580 
03591 dbus_bool_t
03592 dbus_connection_get_unix_process_id (DBusConnection *connection,
03593                                      unsigned long  *pid)
03594 {
03595   dbus_bool_t result;
03596 
03597   _dbus_return_val_if_fail (connection != NULL, FALSE);
03598   _dbus_return_val_if_fail (pid != NULL, FALSE);
03599   
03600   CONNECTION_LOCK (connection);
03601 
03602   if (!_dbus_transport_get_is_authenticated (connection->transport))
03603     result = FALSE;
03604   else
03605     result = _dbus_transport_get_unix_process_id (connection->transport,
03606                                                   pid);
03607   CONNECTION_UNLOCK (connection);
03608 
03609   return result;
03610 }
03611 
03628 void
03629 dbus_connection_set_unix_user_function (DBusConnection             *connection,
03630                                         DBusAllowUnixUserFunction   function,
03631                                         void                       *data,
03632                                         DBusFreeFunction            free_data_function)
03633 {
03634   void *old_data = NULL;
03635   DBusFreeFunction old_free_function = NULL;
03636 
03637   _dbus_return_if_fail (connection != NULL);
03638   
03639   CONNECTION_LOCK (connection);
03640   _dbus_transport_set_unix_user_function (connection->transport,
03641                                           function, data, free_data_function,
03642                                           &old_data, &old_free_function);
03643   CONNECTION_UNLOCK (connection);
03644 
03645   if (old_free_function != NULL)
03646     (* old_free_function) (old_data);    
03647 }
03648 
03670 dbus_bool_t
03671 dbus_connection_add_filter (DBusConnection            *connection,
03672                             DBusHandleMessageFunction  function,
03673                             void                      *user_data,
03674                             DBusFreeFunction           free_data_function)
03675 {
03676   DBusMessageFilter *filter;
03677   
03678   _dbus_return_val_if_fail (connection != NULL, FALSE);
03679   _dbus_return_val_if_fail (function != NULL, FALSE);
03680 
03681   filter = dbus_new0 (DBusMessageFilter, 1);
03682   if (filter == NULL)
03683     return FALSE;
03684 
03685   filter->refcount.value = 1;
03686   
03687   CONNECTION_LOCK (connection);
03688 
03689   if (!_dbus_list_append (&connection->filter_list,
03690                           filter))
03691     {
03692       _dbus_message_filter_unref (filter);
03693       CONNECTION_UNLOCK (connection);
03694       return FALSE;
03695     }
03696 
03697   /* Fill in filter after all memory allocated,
03698    * so we don't run the free_user_data_function
03699    * if the add_filter() fails
03700    */
03701   
03702   filter->function = function;
03703   filter->user_data = user_data;
03704   filter->free_user_data_function = free_data_function;
03705         
03706   CONNECTION_UNLOCK (connection);
03707   return TRUE;
03708 }
03709 
03722 void
03723 dbus_connection_remove_filter (DBusConnection            *connection,
03724                                DBusHandleMessageFunction  function,
03725                                void                      *user_data)
03726 {
03727   DBusList *link;
03728   DBusMessageFilter *filter;
03729   
03730   _dbus_return_if_fail (connection != NULL);
03731   _dbus_return_if_fail (function != NULL);
03732   
03733   CONNECTION_LOCK (connection);
03734 
03735   filter = NULL;
03736   
03737   link = _dbus_list_get_last_link (&connection->filter_list);
03738   while (link != NULL)
03739     {
03740       filter = link->data;
03741 
03742       if (filter->function == function &&
03743           filter->user_data == user_data)
03744         {
03745           _dbus_list_remove_link (&connection->filter_list, link);
03746           filter->function = NULL;
03747           
03748           break;
03749         }
03750         
03751       link = _dbus_list_get_prev_link (&connection->filter_list, link);
03752     }
03753   
03754   CONNECTION_UNLOCK (connection);
03755 
03756 #ifndef DBUS_DISABLE_CHECKS
03757   if (filter == NULL)
03758     {
03759       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
03760                   function, user_data);
03761       return;
03762     }
03763 #endif
03764   
03765   /* Call application code */
03766   if (filter->free_user_data_function)
03767     (* filter->free_user_data_function) (filter->user_data);
03768 
03769   filter->free_user_data_function = NULL;
03770   filter->user_data = NULL;
03771   
03772   _dbus_message_filter_unref (filter);
03773 }
03774 
03786 dbus_bool_t
03787 dbus_connection_register_object_path (DBusConnection              *connection,
03788                                       const char                  *path,
03789                                       const DBusObjectPathVTable  *vtable,
03790                                       void                        *user_data)
03791 {
03792   char **decomposed_path;
03793   dbus_bool_t retval;
03794   
03795   _dbus_return_val_if_fail (connection != NULL, FALSE);
03796   _dbus_return_val_if_fail (path != NULL, FALSE);
03797   _dbus_return_val_if_fail (path[0] == '/', FALSE);
03798   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03799 
03800   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
03801     return FALSE;
03802 
03803   CONNECTION_LOCK (connection);
03804 
03805   retval = _dbus_object_tree_register (connection->objects,
03806                                        FALSE,
03807                                        (const char **) decomposed_path, vtable,
03808                                        user_data);
03809 
03810   CONNECTION_UNLOCK (connection);
03811 
03812   dbus_free_string_array (decomposed_path);
03813 
03814   return retval;
03815 }
03816 
03829 dbus_bool_t
03830 dbus_connection_register_fallback (DBusConnection              *connection,
03831                                    const char                  *path,
03832                                    const DBusObjectPathVTable  *vtable,
03833                                    void                        *user_data)
03834 {
03835   char **decomposed_path;
03836   dbus_bool_t retval;
03837   
03838   _dbus_return_val_if_fail (connection != NULL, FALSE);
03839   _dbus_return_val_if_fail (path != NULL, FALSE);
03840   _dbus_return_val_if_fail (path[0] == '/', FALSE);
03841   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03842 
03843   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
03844     return FALSE;
03845 
03846   CONNECTION_LOCK (connection);
03847 
03848   retval = _dbus_object_tree_register (connection->objects,
03849                                        TRUE,
03850                                        (const char **) decomposed_path, vtable,
03851                                        user_data);
03852 
03853   CONNECTION_UNLOCK (connection);
03854 
03855   dbus_free_string_array (decomposed_path);
03856 
03857   return retval;
03858 }
03859 
03869 dbus_bool_t
03870 dbus_connection_unregister_object_path (DBusConnection              *connection,
03871                                         const char                  *path)
03872 {
03873   char **decomposed_path;
03874 
03875   _dbus_return_val_if_fail (connection != NULL, FALSE);
03876   _dbus_return_val_if_fail (path != NULL, FALSE);
03877   _dbus_return_val_if_fail (path[0] == '/', FALSE);
03878 
03879   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
03880       return FALSE;
03881 
03882   CONNECTION_LOCK (connection);
03883 
03884   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
03885 
03886   dbus_free_string_array (decomposed_path);
03887 
03888   return TRUE;
03889 }
03890 
03901 dbus_bool_t
03902 dbus_connection_list_registered (DBusConnection              *connection,
03903                                  const char                  *parent_path,
03904                                  char                      ***child_entries)
03905 {
03906   char **decomposed_path;
03907   dbus_bool_t retval;
03908   _dbus_return_val_if_fail (connection != NULL, FALSE);
03909   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
03910   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
03911   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
03912 
03913   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
03914     return FALSE;
03915 
03916   CONNECTION_LOCK (connection);
03917 
03918   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
03919                                                          (const char **) decomposed_path,
03920                                                          child_entries);
03921   dbus_free_string_array (decomposed_path);
03922 
03923   return retval;
03924 }
03925 
03926 static DBusDataSlotAllocator slot_allocator;
03927 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
03928 
03943 dbus_bool_t
03944 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
03945 {
03946   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03947                                           _DBUS_LOCK_NAME (connection_slots),
03948                                           slot_p);
03949 }
03950 
03962 void
03963 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
03964 {
03965   _dbus_return_if_fail (*slot_p >= 0);
03966   
03967   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03968 }
03969 
03983 dbus_bool_t
03984 dbus_connection_set_data (DBusConnection   *connection,
03985                           dbus_int32_t      slot,
03986                           void             *data,
03987                           DBusFreeFunction  free_data_func)
03988 {
03989   DBusFreeFunction old_free_func;
03990   void *old_data;
03991   dbus_bool_t retval;
03992 
03993   _dbus_return_val_if_fail (connection != NULL, FALSE);
03994   _dbus_return_val_if_fail (slot >= 0, FALSE);
03995   
03996   CONNECTION_LOCK (connection);
03997 
03998   retval = _dbus_data_slot_list_set (&slot_allocator,
03999                                      &connection->slot_list,
04000                                      slot, data, free_data_func,
04001                                      &old_free_func, &old_data);
04002   
04003   CONNECTION_UNLOCK (connection);
04004 
04005   if (retval)
04006     {
04007       /* Do the actual free outside the connection lock */
04008       if (old_free_func)
04009         (* old_free_func) (old_data);
04010     }
04011 
04012   return retval;
04013 }
04014 
04023 void*
04024 dbus_connection_get_data (DBusConnection   *connection,
04025                           dbus_int32_t      slot)
04026 {
04027   void *res;
04028 
04029   _dbus_return_val_if_fail (connection != NULL, NULL);
04030   
04031   CONNECTION_LOCK (connection);
04032 
04033   res = _dbus_data_slot_list_get (&slot_allocator,
04034                                   &connection->slot_list,
04035                                   slot);
04036   
04037   CONNECTION_UNLOCK (connection);
04038 
04039   return res;
04040 }
04041 
04048 void
04049 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04050 {  
04051   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04052 }
04053 
04062 void
04063 dbus_connection_set_max_message_size (DBusConnection *connection,
04064                                       long            size)
04065 {
04066   _dbus_return_if_fail (connection != NULL);
04067   
04068   CONNECTION_LOCK (connection);
04069   _dbus_transport_set_max_message_size (connection->transport,
04070                                         size);
04071   CONNECTION_UNLOCK (connection);
04072 }
04073 
04080 long
04081 dbus_connection_get_max_message_size (DBusConnection *connection)
04082 {
04083   long res;
04084 
04085   _dbus_return_val_if_fail (connection != NULL, 0);
04086   
04087   CONNECTION_LOCK (connection);
04088   res = _dbus_transport_get_max_message_size (connection->transport);
04089   CONNECTION_UNLOCK (connection);
04090   return res;
04091 }
04092 
04118 void
04119 dbus_connection_set_max_received_size (DBusConnection *connection,
04120                                        long            size)
04121 {
04122   _dbus_return_if_fail (connection != NULL);
04123   
04124   CONNECTION_LOCK (connection);
04125   _dbus_transport_set_max_received_size (connection->transport,
04126                                          size);
04127   CONNECTION_UNLOCK (connection);
04128 }
04129 
04136 long
04137 dbus_connection_get_max_received_size (DBusConnection *connection)
04138 {
04139   long res;
04140 
04141   _dbus_return_val_if_fail (connection != NULL, 0);
04142   
04143   CONNECTION_LOCK (connection);
04144   res = _dbus_transport_get_max_received_size (connection->transport);
04145   CONNECTION_UNLOCK (connection);
04146   return res;
04147 }
04148 
04159 long
04160 dbus_connection_get_outgoing_size (DBusConnection *connection)
04161 {
04162   long res;
04163 
04164   _dbus_return_val_if_fail (connection != NULL, 0);
04165   
04166   CONNECTION_LOCK (connection);
04167   res = _dbus_counter_get_value (connection->outgoing_counter);
04168   CONNECTION_UNLOCK (connection);
04169   return res;
04170 }
04171 

Generated on Mon Apr 4 04:40:46 2005 for D-BUS by  doxygen 1.4.0