Main Page | Modules | Data Structures | 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  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 #if 0
00044 #define CONNECTION_LOCK(connection)   do {                      \
00045     _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME);        \
00046     dbus_mutex_lock ((connection)->mutex);                      \
00047   } while (0)
00048 #define CONNECTION_UNLOCK(connection) do {                      \
00049     _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);      \
00050     dbus_mutex_unlock ((connection)->mutex);                    \
00051   } while (0)
00052 #else
00053 #define CONNECTION_LOCK(connection)    dbus_mutex_lock ((connection)->mutex)
00054 #define CONNECTION_UNLOCK(connection)  dbus_mutex_unlock ((connection)->mutex)
00055 #endif
00056 
00134 typedef struct DBusMessageFilter DBusMessageFilter;
00135 
00139 struct DBusMessageFilter
00140 {
00141   DBusAtomic refcount; 
00142   DBusHandleMessageFunction function; 
00143   void *user_data; 
00144   DBusFreeFunction free_user_data_function; 
00145 };
00146 
00147 
00151 struct DBusPreallocatedSend
00152 {
00153   DBusConnection *connection; 
00154   DBusList *queue_link;       
00155   DBusList *counter_link;     
00156 };
00157 
00158 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00159 
00163 struct DBusConnection
00164 {
00165   DBusAtomic refcount; 
00167   DBusMutex *mutex; 
00169   dbus_bool_t dispatch_acquired; 
00170   DBusCondVar *dispatch_cond;    
00172   dbus_bool_t io_path_acquired;  
00173   DBusCondVar *io_path_cond;     
00175   DBusList *outgoing_messages; 
00176   DBusList *incoming_messages; 
00178   DBusMessage *message_borrowed; 
00179   DBusCondVar *message_returned_cond; 
00181   int n_outgoing;              
00182   int n_incoming;              
00184   DBusCounter *outgoing_counter; 
00186   DBusTransport *transport;    
00187   DBusWatchList *watches;      
00188   DBusTimeoutList *timeouts;   
00190   DBusList *filter_list;        
00192   DBusDataSlotList slot_list;   
00194   DBusHashTable *pending_replies;  
00196   dbus_uint32_t client_serial;       
00197   DBusList *disconnect_message_link; 
00199   DBusWakeupMainFunction wakeup_main_function; 
00200   void *wakeup_main_data; 
00201   DBusFreeFunction free_wakeup_main_data; 
00203   DBusDispatchStatusFunction dispatch_status_function; 
00204   void *dispatch_status_data; 
00205   DBusFreeFunction free_dispatch_status_data; 
00207   DBusDispatchStatus last_dispatch_status; 
00209   DBusList *link_cache; 
00212   DBusObjectTree *objects; 
00214   unsigned int exit_on_disconnect : 1; 
00215 };
00216 
00217 static void               _dbus_connection_remove_timeout_locked             (DBusConnection     *connection,
00218                                                                               DBusTimeout        *timeout);
00219 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00220 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00221                                                                               DBusDispatchStatus  new_status);
00222 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00223 
00224 static DBusMessageFilter *
00225 _dbus_message_filter_ref (DBusMessageFilter *filter)
00226 {
00227   _dbus_assert (filter->refcount.value > 0);
00228   _dbus_atomic_inc (&filter->refcount);
00229 
00230   return filter;
00231 }
00232 
00233 static void
00234 _dbus_message_filter_unref (DBusMessageFilter *filter)
00235 {
00236   _dbus_assert (filter->refcount.value > 0);
00237 
00238   if (_dbus_atomic_dec (&filter->refcount) == 1)
00239     {
00240       if (filter->free_user_data_function)
00241         (* filter->free_user_data_function) (filter->user_data);
00242       
00243       dbus_free (filter);
00244     }
00245 }
00246 
00252 void
00253 _dbus_connection_lock (DBusConnection *connection)
00254 {
00255   CONNECTION_LOCK (connection);
00256 }
00257 
00263 void
00264 _dbus_connection_unlock (DBusConnection *connection)
00265 {
00266   CONNECTION_UNLOCK (connection);
00267 }
00268 
00276 static void
00277 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00278 {
00279   if (connection->wakeup_main_function)
00280     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00281 }
00282 
00283 #ifdef DBUS_BUILD_TESTS
00284 /* For now this function isn't used */
00294 dbus_bool_t
00295 _dbus_connection_queue_received_message (DBusConnection *connection,
00296                                          DBusMessage    *message)
00297 {
00298   DBusList *link;
00299 
00300   link = _dbus_list_alloc_link (message);
00301   if (link == NULL)
00302     return FALSE;
00303 
00304   dbus_message_ref (message);
00305   _dbus_connection_queue_received_message_link (connection, link);
00306 
00307   return TRUE;
00308 }
00309 #endif
00310 
00319 void
00320 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00321                                               DBusList        *link)
00322 {
00323   DBusPendingCall *pending;
00324   dbus_int32_t reply_serial;
00325   DBusMessage *message;
00326   
00327   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00328   
00329   _dbus_list_append_link (&connection->incoming_messages,
00330                           link);
00331   message = link->data;
00332 
00333   /* If this is a reply we're waiting on, remove timeout for it */
00334   reply_serial = dbus_message_get_reply_serial (message);
00335   if (reply_serial != -1)
00336     {
00337       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00338                                              reply_serial);
00339       if (pending != NULL)
00340         {
00341           if (pending->timeout_added)
00342             _dbus_connection_remove_timeout_locked (connection,
00343                                                     pending->timeout);
00344 
00345           pending->timeout_added = FALSE;
00346         }
00347     }
00348   
00349   connection->n_incoming += 1;
00350 
00351   _dbus_connection_wakeup_mainloop (connection);
00352   
00353   _dbus_verbose ("Message %p (%d %s '%s') added to incoming queue %p, %d incoming\n",
00354                  message,
00355                  dbus_message_get_type (message),
00356                  dbus_message_get_interface (message) ?
00357                  dbus_message_get_interface (message) :
00358                  "no interface",
00359                  dbus_message_get_signature (message),
00360                  connection,
00361                  connection->n_incoming);
00362 }
00363 
00374 static void
00375 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00376                                                  DBusList *link)
00377 {
00378   _dbus_list_append_link (&connection->incoming_messages, link);
00379 
00380   connection->n_incoming += 1;
00381 
00382   _dbus_connection_wakeup_mainloop (connection);
00383   
00384   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00385                  link->data, connection, connection->n_incoming);
00386 }
00387 
00388 
00395 dbus_bool_t
00396 _dbus_connection_have_messages_to_send (DBusConnection *connection)
00397 {
00398   return connection->outgoing_messages != NULL;
00399 }
00400 
00408 DBusMessage*
00409 _dbus_connection_get_message_to_send (DBusConnection *connection)
00410 {
00411   return _dbus_list_get_last (&connection->outgoing_messages);
00412 }
00413 
00422 void
00423 _dbus_connection_message_sent (DBusConnection *connection,
00424                                DBusMessage    *message)
00425 {
00426   DBusList *link;
00427   
00428   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00429   
00430   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00431   _dbus_assert (link != NULL);
00432   _dbus_assert (link->data == message);
00433 
00434   /* Save this link in the link cache */
00435   _dbus_list_unlink (&connection->outgoing_messages,
00436                      link);
00437   _dbus_list_prepend_link (&connection->link_cache, link);
00438   
00439   connection->n_outgoing -= 1;
00440 
00441   _dbus_verbose ("Message %p (%d %s '%s') removed from outgoing queue %p, %d left to send\n",
00442                  message,
00443                  dbus_message_get_type (message),
00444                  dbus_message_get_interface (message) ?
00445                  dbus_message_get_interface (message) :
00446                  "no interface",
00447                  dbus_message_get_signature (message),
00448                  connection, connection->n_outgoing);
00449 
00450   /* Save this link in the link cache also */
00451   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00452                                      &link);
00453   _dbus_list_prepend_link (&connection->link_cache, link);
00454   
00455   dbus_message_unref (message);
00456   
00457   if (connection->n_outgoing == 0)
00458     _dbus_transport_messages_pending (connection->transport,
00459                                       connection->n_outgoing);  
00460 }
00461 
00472 dbus_bool_t
00473 _dbus_connection_add_watch (DBusConnection *connection,
00474                             DBusWatch      *watch)
00475 {
00476   if (connection->watches) /* null during finalize */
00477     return _dbus_watch_list_add_watch (connection->watches,
00478                                        watch);
00479   else
00480     return FALSE;
00481 }
00482 
00491 void
00492 _dbus_connection_remove_watch (DBusConnection *connection,
00493                                DBusWatch      *watch)
00494 {
00495   if (connection->watches) /* null during finalize */
00496     _dbus_watch_list_remove_watch (connection->watches,
00497                                    watch);
00498 }
00499 
00509 void
00510 _dbus_connection_toggle_watch (DBusConnection *connection,
00511                                DBusWatch      *watch,
00512                                dbus_bool_t     enabled)
00513 {
00514   if (connection->watches) /* null during finalize */
00515     _dbus_watch_list_toggle_watch (connection->watches,
00516                                    watch, enabled);
00517 }
00518 
00530 dbus_bool_t
00531 _dbus_connection_add_timeout (DBusConnection *connection,
00532                               DBusTimeout    *timeout)
00533 {
00534  if (connection->timeouts) /* null during finalize */
00535     return _dbus_timeout_list_add_timeout (connection->timeouts,
00536                                            timeout);
00537   else
00538     return FALSE;  
00539 }
00540 
00549 void
00550 _dbus_connection_remove_timeout (DBusConnection *connection,
00551                                  DBusTimeout    *timeout)
00552 {
00553   if (connection->timeouts) /* null during finalize */
00554     _dbus_timeout_list_remove_timeout (connection->timeouts,
00555                                        timeout);
00556 }
00557 
00558 static void
00559 _dbus_connection_remove_timeout_locked (DBusConnection *connection,
00560                                         DBusTimeout    *timeout)
00561 {
00562   CONNECTION_LOCK (connection);
00563   _dbus_connection_remove_timeout (connection, timeout);
00564   CONNECTION_UNLOCK (connection);
00565 }
00566 
00576 void
00577 _dbus_connection_toggle_timeout (DBusConnection *connection,
00578                                  DBusTimeout      *timeout,
00579                                  dbus_bool_t     enabled)
00580 {
00581   if (connection->timeouts) /* null during finalize */
00582     _dbus_timeout_list_toggle_timeout (connection->timeouts,
00583                                        timeout, enabled);
00584 }
00585 
00586 static dbus_bool_t
00587 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00588                                                DBusPendingCall *pending)
00589 {
00590   _dbus_assert (pending->reply_serial != 0);
00591 
00592   if (!_dbus_connection_add_timeout (connection, pending->timeout))
00593     return FALSE;
00594   
00595   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00596                                     pending->reply_serial,
00597                                     pending))
00598     {
00599       _dbus_connection_remove_timeout (connection, pending->timeout);
00600       return FALSE;
00601     }
00602   
00603   pending->timeout_added = TRUE;
00604   pending->connection = connection;
00605 
00606   dbus_pending_call_ref (pending);
00607   
00608   return TRUE;
00609 }
00610 
00611 static void
00612 free_pending_call_on_hash_removal (void *data)
00613 {
00614   DBusPendingCall *pending;
00615   
00616   if (data == NULL)
00617     return;
00618 
00619   pending = data;
00620 
00621   if (pending->connection)
00622     {
00623       if (pending->timeout_added)
00624         {
00625           _dbus_connection_remove_timeout (pending->connection,
00626                                            pending->timeout);
00627           pending->timeout_added = FALSE;
00628         }
00629 
00630       pending->connection = NULL;
00631       
00632       dbus_pending_call_unref (pending);
00633     }
00634 }
00635 
00636 static void
00637 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00638                                                  DBusPendingCall *pending)
00639 {
00640   /* The idea here is to avoid finalizing the pending call
00641    * with the lock held, since there's a destroy notifier
00642    * in pending call that goes out to application code.
00643    */
00644   dbus_pending_call_ref (pending);
00645   _dbus_hash_table_remove_int (connection->pending_replies,
00646                                pending->reply_serial);
00647   CONNECTION_UNLOCK (connection);
00648   dbus_pending_call_unref (pending);
00649 }
00650 
00659 void
00660 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00661                                       DBusPendingCall *pending)
00662 {
00663   CONNECTION_LOCK (connection);
00664   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00665 }
00666 
00675 void
00676 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00677                                         DBusMessage     *message)
00678 {
00679   if (message == NULL)
00680     {
00681       message = pending->timeout_link->data;
00682       _dbus_list_clear (&pending->timeout_link);
00683     }
00684   else
00685     dbus_message_ref (message);
00686 
00687   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
00688                  message,
00689                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00690                  "method return" :
00691                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00692                  "error" : "other type",
00693                  pending->reply_serial);
00694   
00695   _dbus_assert (pending->reply == NULL);
00696   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00697   pending->reply = message;
00698   
00699   dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
00700   _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00701   
00702   /* Must be called unlocked since it invokes app callback */
00703   _dbus_pending_call_notify (pending);
00704   dbus_pending_call_unref (pending);
00705 }
00706 
00716 static dbus_bool_t
00717 _dbus_connection_acquire_io_path (DBusConnection *connection,
00718                                   int timeout_milliseconds)
00719 {
00720   dbus_bool_t res = TRUE;
00721 
00722   if (connection->io_path_acquired)
00723     {
00724       if (timeout_milliseconds != -1) 
00725         res = dbus_condvar_wait_timeout (connection->io_path_cond,
00726                                          connection->mutex,
00727                                          timeout_milliseconds);
00728       else
00729         dbus_condvar_wait (connection->io_path_cond, connection->mutex);
00730     }
00731   
00732   if (res)
00733     {
00734       _dbus_assert (!connection->io_path_acquired);
00735 
00736       connection->io_path_acquired = TRUE;
00737     }
00738   
00739   return res;
00740 }
00741 
00749 static void
00750 _dbus_connection_release_io_path (DBusConnection *connection)
00751 {
00752   _dbus_assert (connection->io_path_acquired);
00753 
00754   connection->io_path_acquired = FALSE;
00755   dbus_condvar_wake_one (connection->io_path_cond);
00756 }
00757 
00758 
00785 void
00786 _dbus_connection_do_iteration (DBusConnection *connection,
00787                                unsigned int    flags,
00788                                int             timeout_milliseconds)
00789 {
00790   if (connection->n_outgoing == 0)
00791     flags &= ~DBUS_ITERATION_DO_WRITING;
00792 
00793   if (_dbus_connection_acquire_io_path (connection,
00794                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
00795     {
00796       _dbus_transport_do_iteration (connection->transport,
00797                                     flags, timeout_milliseconds);
00798       _dbus_connection_release_io_path (connection);
00799     }
00800 }
00801 
00811 DBusConnection*
00812 _dbus_connection_new_for_transport (DBusTransport *transport)
00813 {
00814   DBusConnection *connection;
00815   DBusWatchList *watch_list;
00816   DBusTimeoutList *timeout_list;
00817   DBusHashTable *pending_replies;
00818   DBusMutex *mutex;
00819   DBusCondVar *message_returned_cond;
00820   DBusCondVar *dispatch_cond;
00821   DBusCondVar *io_path_cond;
00822   DBusList *disconnect_link;
00823   DBusMessage *disconnect_message;
00824   DBusCounter *outgoing_counter;
00825   DBusObjectTree *objects;
00826   
00827   watch_list = NULL;
00828   connection = NULL;
00829   pending_replies = NULL;
00830   timeout_list = NULL;
00831   mutex = NULL;
00832   message_returned_cond = NULL;
00833   dispatch_cond = NULL;
00834   io_path_cond = NULL;
00835   disconnect_link = NULL;
00836   disconnect_message = NULL;
00837   outgoing_counter = NULL;
00838   objects = NULL;
00839   
00840   watch_list = _dbus_watch_list_new ();
00841   if (watch_list == NULL)
00842     goto error;
00843 
00844   timeout_list = _dbus_timeout_list_new ();
00845   if (timeout_list == NULL)
00846     goto error;  
00847 
00848   pending_replies =
00849     _dbus_hash_table_new (DBUS_HASH_INT,
00850                           NULL,
00851                           (DBusFreeFunction)free_pending_call_on_hash_removal);
00852   if (pending_replies == NULL)
00853     goto error;
00854   
00855   connection = dbus_new0 (DBusConnection, 1);
00856   if (connection == NULL)
00857     goto error;
00858 
00859   mutex = dbus_mutex_new ();
00860   if (mutex == NULL)
00861     goto error;
00862   
00863   message_returned_cond = dbus_condvar_new ();
00864   if (message_returned_cond == NULL)
00865     goto error;
00866   
00867   dispatch_cond = dbus_condvar_new ();
00868   if (dispatch_cond == NULL)
00869     goto error;
00870   
00871   io_path_cond = dbus_condvar_new ();
00872   if (io_path_cond == NULL)
00873     goto error;
00874 
00875   disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL,
00876                                                 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
00877                                                 "Disconnected");
00878   
00879   if (disconnect_message == NULL)
00880     goto error;
00881 
00882   disconnect_link = _dbus_list_alloc_link (disconnect_message);
00883   if (disconnect_link == NULL)
00884     goto error;
00885 
00886   outgoing_counter = _dbus_counter_new ();
00887   if (outgoing_counter == NULL)
00888     goto error;
00889 
00890   objects = _dbus_object_tree_new (connection);
00891   if (objects == NULL)
00892     goto error;
00893   
00894   if (_dbus_modify_sigpipe)
00895     _dbus_disable_sigpipe ();
00896   
00897   connection->refcount.value = 1;
00898   connection->mutex = mutex;
00899   connection->dispatch_cond = dispatch_cond;
00900   connection->io_path_cond = io_path_cond;
00901   connection->message_returned_cond = message_returned_cond;
00902   connection->transport = transport;
00903   connection->watches = watch_list;
00904   connection->timeouts = timeout_list;
00905   connection->pending_replies = pending_replies;
00906   connection->outgoing_counter = outgoing_counter;
00907   connection->filter_list = NULL;
00908   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
00909   connection->objects = objects;
00910   connection->exit_on_disconnect = FALSE;
00911   
00912   _dbus_data_slot_list_init (&connection->slot_list);
00913 
00914   connection->client_serial = 1;
00915 
00916   connection->disconnect_message_link = disconnect_link;
00917   
00918   if (!_dbus_transport_set_connection (transport, connection))
00919     goto error;
00920 
00921   _dbus_transport_ref (transport);  
00922   
00923   return connection;
00924   
00925  error:
00926   if (disconnect_message != NULL)
00927     dbus_message_unref (disconnect_message);
00928   
00929   if (disconnect_link != NULL)
00930     _dbus_list_free_link (disconnect_link);
00931   
00932   if (io_path_cond != NULL)
00933     dbus_condvar_free (io_path_cond);
00934   
00935   if (dispatch_cond != NULL)
00936     dbus_condvar_free (dispatch_cond);
00937   
00938   if (message_returned_cond != NULL)
00939     dbus_condvar_free (message_returned_cond);
00940   
00941   if (mutex != NULL)
00942     dbus_mutex_free (mutex);
00943 
00944   if (connection != NULL)
00945     dbus_free (connection);
00946 
00947   if (pending_replies)
00948     _dbus_hash_table_unref (pending_replies);
00949   
00950   if (watch_list)
00951     _dbus_watch_list_free (watch_list);
00952 
00953   if (timeout_list)
00954     _dbus_timeout_list_free (timeout_list);
00955 
00956   if (outgoing_counter)
00957     _dbus_counter_unref (outgoing_counter);
00958 
00959   if (objects)
00960     _dbus_object_tree_unref (objects);
00961   
00962   return NULL;
00963 }
00964 
00972 DBusConnection *
00973 _dbus_connection_ref_unlocked (DBusConnection *connection)
00974 {
00975 #ifdef DBUS_HAVE_ATOMIC_INT
00976   _dbus_atomic_inc (&connection->refcount);
00977 #else
00978   _dbus_assert (connection->refcount.value > 0);
00979   connection->refcount.value += 1;
00980 #endif
00981 
00982   return connection;
00983 }
00984 
00991 void
00992 _dbus_connection_unref_unlocked (DBusConnection *connection)
00993 {
00994   dbus_bool_t last_unref;
00995 
00996   _dbus_return_if_fail (connection != NULL);
00997 
00998   /* The connection lock is better than the global
00999    * lock in the atomic increment fallback
01000    */
01001   
01002 #ifdef DBUS_HAVE_ATOMIC_INT
01003   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01004 #else  
01005   _dbus_assert (connection->refcount.value > 0);
01006 
01007   connection->refcount.value -= 1;
01008   last_unref = (connection->refcount.value == 0);
01009 #if 0
01010   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01011 #endif
01012 #endif
01013   
01014   if (last_unref)
01015     _dbus_connection_last_unref (connection);
01016 }
01017 
01018 static dbus_uint32_t
01019 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01020 {
01021   int serial;
01022 
01023   serial = connection->client_serial++;
01024 
01025   if (connection->client_serial < 0)
01026     connection->client_serial = 1;
01027   
01028   return serial;
01029 }
01030 
01044 dbus_bool_t
01045 _dbus_connection_handle_watch (DBusWatch                   *watch,
01046                                unsigned int                 condition,
01047                                void                        *data)
01048 {
01049   DBusConnection *connection;
01050   dbus_bool_t retval;
01051   DBusDispatchStatus status;
01052 
01053   connection = data;
01054   
01055   CONNECTION_LOCK (connection);
01056   _dbus_connection_acquire_io_path (connection, -1);
01057   retval = _dbus_transport_handle_watch (connection->transport,
01058                                          watch, condition);
01059   _dbus_connection_release_io_path (connection);
01060 
01061   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01062 
01063   /* this calls out to user code */
01064   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01065   
01066   return retval;
01067 }
01068 
01093 DBusConnection*
01094 dbus_connection_open (const char     *address,
01095                       DBusError      *error)
01096 {
01097   DBusConnection *connection;
01098   DBusTransport *transport;
01099 
01100   _dbus_return_val_if_fail (address != NULL, NULL);
01101   _dbus_return_val_if_error_is_set (error, NULL);
01102   
01103   transport = _dbus_transport_open (address, error);
01104   if (transport == NULL)
01105     {
01106       _DBUS_ASSERT_ERROR_IS_SET (error);
01107       return NULL;
01108     }
01109   
01110   connection = _dbus_connection_new_for_transport (transport);
01111 
01112   _dbus_transport_unref (transport);
01113   
01114   if (connection == NULL)
01115     {
01116       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01117       return NULL;
01118     }
01119   
01120   return connection;
01121 }
01122 
01129 DBusConnection *
01130 dbus_connection_ref (DBusConnection *connection)
01131 {
01132   _dbus_return_val_if_fail (connection != NULL, NULL);
01133 
01134   /* The connection lock is better than the global
01135    * lock in the atomic increment fallback
01136    */
01137   
01138 #ifdef DBUS_HAVE_ATOMIC_INT
01139   _dbus_atomic_inc (&connection->refcount);
01140 #else
01141   CONNECTION_LOCK (connection);
01142   _dbus_assert (connection->refcount.value > 0);
01143 
01144   connection->refcount.value += 1;
01145   CONNECTION_UNLOCK (connection);
01146 #endif
01147 
01148   return connection;
01149 }
01150 
01151 static void
01152 free_outgoing_message (void *element,
01153                        void *data)
01154 {
01155   DBusMessage *message = element;
01156   DBusConnection *connection = data;
01157 
01158   _dbus_message_remove_size_counter (message,
01159                                      connection->outgoing_counter,
01160                                      NULL);
01161   dbus_message_unref (message);
01162 }
01163 
01164 /* This is run without the mutex held, but after the last reference
01165  * to the connection has been dropped we should have no thread-related
01166  * problems
01167  */
01168 static void
01169 _dbus_connection_last_unref (DBusConnection *connection)
01170 {
01171   DBusList *link;
01172 
01173   _dbus_verbose ("Finalizing connection %p\n", connection);
01174   
01175   _dbus_assert (connection->refcount.value == 0);
01176   
01177   /* You have to disconnect the connection before unref:ing it. Otherwise
01178    * you won't get the disconnected message.
01179    */
01180   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01181 
01182   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01183   _dbus_object_tree_free_all_unlocked (connection->objects);
01184   
01185   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01186   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01187   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01188   
01189   _dbus_watch_list_free (connection->watches);
01190   connection->watches = NULL;
01191   
01192   _dbus_timeout_list_free (connection->timeouts);
01193   connection->timeouts = NULL;
01194 
01195   _dbus_data_slot_list_free (&connection->slot_list);
01196   
01197   link = _dbus_list_get_first_link (&connection->filter_list);
01198   while (link != NULL)
01199     {
01200       DBusMessageFilter *filter = link->data;
01201       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01202 
01203       filter->function = NULL;
01204       _dbus_message_filter_unref (filter); /* calls app callback */
01205       link->data = NULL;
01206       
01207       link = next;
01208     }
01209   _dbus_list_clear (&connection->filter_list);
01210   
01211   /* ---- Done with stuff that invokes application callbacks */
01212 
01213   _dbus_object_tree_unref (connection->objects);  
01214 
01215   _dbus_hash_table_unref (connection->pending_replies);
01216   connection->pending_replies = NULL;
01217   
01218   _dbus_list_clear (&connection->filter_list);
01219   
01220   _dbus_list_foreach (&connection->outgoing_messages,
01221                       free_outgoing_message,
01222                       connection);
01223   _dbus_list_clear (&connection->outgoing_messages);
01224   
01225   _dbus_list_foreach (&connection->incoming_messages,
01226                       (DBusForeachFunction) dbus_message_unref,
01227                       NULL);
01228   _dbus_list_clear (&connection->incoming_messages);
01229 
01230   _dbus_counter_unref (connection->outgoing_counter);
01231   
01232   _dbus_transport_unref (connection->transport);
01233 
01234   if (connection->disconnect_message_link)
01235     {
01236       DBusMessage *message = connection->disconnect_message_link->data;
01237       dbus_message_unref (message);
01238       _dbus_list_free_link (connection->disconnect_message_link);
01239     }
01240 
01241   _dbus_list_clear (&connection->link_cache);
01242   
01243   dbus_condvar_free (connection->dispatch_cond);
01244   dbus_condvar_free (connection->io_path_cond);
01245   dbus_condvar_free (connection->message_returned_cond);  
01246   
01247   dbus_mutex_free (connection->mutex);
01248   
01249   dbus_free (connection);
01250 }
01251 
01263 void
01264 dbus_connection_unref (DBusConnection *connection)
01265 {
01266   dbus_bool_t last_unref;
01267 
01268   _dbus_return_if_fail (connection != NULL);
01269 
01270   /* The connection lock is better than the global
01271    * lock in the atomic increment fallback
01272    */
01273   
01274 #ifdef DBUS_HAVE_ATOMIC_INT
01275   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01276 #else
01277   CONNECTION_LOCK (connection);
01278   
01279   _dbus_assert (connection->refcount.value > 0);
01280 
01281   connection->refcount.value -= 1;
01282   last_unref = (connection->refcount.value == 0);
01283 
01284 #if 0
01285   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01286 #endif
01287   
01288   CONNECTION_UNLOCK (connection);
01289 #endif
01290   
01291   if (last_unref)
01292     _dbus_connection_last_unref (connection);
01293 }
01294 
01308 void
01309 dbus_connection_disconnect (DBusConnection *connection)
01310 {
01311   DBusDispatchStatus status;
01312   
01313   _dbus_return_if_fail (connection != NULL);
01314   
01315   CONNECTION_LOCK (connection);
01316   _dbus_transport_disconnect (connection->transport);
01317   
01318   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01319 
01320   /* this calls out to user code */
01321   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01322 }
01323 
01324 static dbus_bool_t
01325 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01326 {
01327   return _dbus_transport_get_is_connected (connection->transport);
01328 }
01329 
01340 dbus_bool_t
01341 dbus_connection_get_is_connected (DBusConnection *connection)
01342 {
01343   dbus_bool_t res;
01344 
01345   _dbus_return_val_if_fail (connection != NULL, FALSE);
01346   
01347   CONNECTION_LOCK (connection);
01348   res = _dbus_connection_get_is_connected_unlocked (connection);
01349   CONNECTION_UNLOCK (connection);
01350   
01351   return res;
01352 }
01353 
01362 dbus_bool_t
01363 dbus_connection_get_is_authenticated (DBusConnection *connection)
01364 {
01365   dbus_bool_t res;
01366 
01367   _dbus_return_val_if_fail (connection != NULL, FALSE);
01368   
01369   CONNECTION_LOCK (connection);
01370   res = _dbus_transport_get_is_authenticated (connection->transport);
01371   CONNECTION_UNLOCK (connection);
01372   
01373   return res;
01374 }
01375 
01389 void
01390 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
01391                                         dbus_bool_t     exit_on_disconnect)
01392 {
01393   _dbus_return_if_fail (connection != NULL);
01394 
01395   CONNECTION_LOCK (connection);
01396   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
01397   CONNECTION_UNLOCK (connection);
01398 }
01399 
01400 static DBusPreallocatedSend*
01401 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01402 {
01403   DBusPreallocatedSend *preallocated;
01404 
01405   _dbus_return_val_if_fail (connection != NULL, NULL);
01406   
01407   preallocated = dbus_new (DBusPreallocatedSend, 1);
01408   if (preallocated == NULL)
01409     return NULL;
01410 
01411   if (connection->link_cache != NULL)
01412     {
01413       preallocated->queue_link =
01414         _dbus_list_pop_first_link (&connection->link_cache);
01415       preallocated->queue_link->data = NULL;
01416     }
01417   else
01418     {
01419       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01420       if (preallocated->queue_link == NULL)
01421         goto failed_0;
01422     }
01423   
01424   if (connection->link_cache != NULL)
01425     {
01426       preallocated->counter_link =
01427         _dbus_list_pop_first_link (&connection->link_cache);
01428       preallocated->counter_link->data = connection->outgoing_counter;
01429     }
01430   else
01431     {
01432       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01433       if (preallocated->counter_link == NULL)
01434         goto failed_1;
01435     }
01436 
01437   _dbus_counter_ref (preallocated->counter_link->data);
01438 
01439   preallocated->connection = connection;
01440   
01441   return preallocated;
01442   
01443  failed_1:
01444   _dbus_list_free_link (preallocated->queue_link);
01445  failed_0:
01446   dbus_free (preallocated);
01447   
01448   return NULL;
01449 }
01450 
01460 DBusPreallocatedSend*
01461 dbus_connection_preallocate_send (DBusConnection *connection)
01462 {
01463   DBusPreallocatedSend *preallocated;
01464 
01465   _dbus_return_val_if_fail (connection != NULL, NULL);
01466 
01467   CONNECTION_LOCK (connection);
01468   
01469   preallocated =
01470     _dbus_connection_preallocate_send_unlocked (connection);
01471 
01472   CONNECTION_UNLOCK (connection);
01473 
01474   return preallocated;
01475 }
01476 
01486 void
01487 dbus_connection_free_preallocated_send (DBusConnection       *connection,
01488                                         DBusPreallocatedSend *preallocated)
01489 {
01490   _dbus_return_if_fail (connection != NULL);
01491   _dbus_return_if_fail (preallocated != NULL);  
01492   _dbus_return_if_fail (connection == preallocated->connection);
01493 
01494   _dbus_list_free_link (preallocated->queue_link);
01495   _dbus_counter_unref (preallocated->counter_link->data);
01496   _dbus_list_free_link (preallocated->counter_link);
01497   dbus_free (preallocated);
01498 }
01499 
01500 static void
01501 _dbus_connection_send_preallocated_unlocked (DBusConnection       *connection,
01502                                              DBusPreallocatedSend *preallocated,
01503                                              DBusMessage          *message,
01504                                              dbus_uint32_t        *client_serial)
01505 {
01506   dbus_uint32_t serial;
01507 
01508   preallocated->queue_link->data = message;
01509   _dbus_list_prepend_link (&connection->outgoing_messages,
01510                            preallocated->queue_link);
01511 
01512   _dbus_message_add_size_counter_link (message,
01513                                        preallocated->counter_link);
01514 
01515   dbus_free (preallocated);
01516   preallocated = NULL;
01517   
01518   dbus_message_ref (message);
01519   
01520   connection->n_outgoing += 1;
01521 
01522   _dbus_verbose ("Message %p (%d %s '%s') added to outgoing queue %p, %d pending to send\n",
01523                  message,
01524                  dbus_message_get_type (message),
01525                  dbus_message_get_interface (message) ?
01526                  dbus_message_get_interface (message) :
01527                  "no interface",
01528                  dbus_message_get_signature (message),
01529                  connection,
01530                  connection->n_outgoing);
01531 
01532   if (dbus_message_get_serial (message) == 0)
01533     {
01534       serial = _dbus_connection_get_next_client_serial (connection);
01535       _dbus_message_set_serial (message, serial);
01536       if (client_serial)
01537         *client_serial = serial;
01538     }
01539   else
01540     {
01541       if (client_serial)
01542         *client_serial = dbus_message_get_serial (message);
01543     }
01544   
01545   _dbus_message_lock (message);
01546 
01547   if (connection->n_outgoing == 1)
01548     _dbus_transport_messages_pending (connection->transport,
01549                                       connection->n_outgoing);
01550   
01551   _dbus_connection_wakeup_mainloop (connection);
01552 }
01553 
01566 void
01567 dbus_connection_send_preallocated (DBusConnection       *connection,
01568                                    DBusPreallocatedSend *preallocated,
01569                                    DBusMessage          *message,
01570                                    dbus_uint32_t        *client_serial)
01571 {
01572   _dbus_return_if_fail (connection != NULL);
01573   _dbus_return_if_fail (preallocated != NULL);
01574   _dbus_return_if_fail (message != NULL);
01575   _dbus_return_if_fail (preallocated->connection == connection);
01576   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
01577                         (dbus_message_get_interface (message) != NULL &&
01578                          dbus_message_get_member (message) != NULL));
01579   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
01580                         (dbus_message_get_interface (message) != NULL &&
01581                          dbus_message_get_member (message) != NULL));
01582   
01583   CONNECTION_LOCK (connection);
01584   _dbus_connection_send_preallocated_unlocked (connection,
01585                                                preallocated,
01586                                                message, client_serial);
01587   CONNECTION_UNLOCK (connection);  
01588 }
01589 
01590 static dbus_bool_t
01591 _dbus_connection_send_unlocked (DBusConnection *connection,
01592                                 DBusMessage    *message,
01593                                 dbus_uint32_t  *client_serial)
01594 {
01595   DBusPreallocatedSend *preallocated;
01596 
01597   _dbus_assert (connection != NULL);
01598   _dbus_assert (message != NULL);
01599   
01600   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01601   if (preallocated == NULL)
01602     return FALSE;
01603 
01604 
01605   _dbus_connection_send_preallocated_unlocked (connection,
01606                                                preallocated,
01607                                                message,
01608                                                client_serial);
01609   return TRUE;
01610 }
01611 
01630 dbus_bool_t
01631 dbus_connection_send (DBusConnection *connection,
01632                       DBusMessage    *message,
01633                       dbus_uint32_t  *client_serial)
01634 {
01635   _dbus_return_val_if_fail (connection != NULL, FALSE);
01636   _dbus_return_val_if_fail (message != NULL, FALSE);
01637 
01638   CONNECTION_LOCK (connection);
01639 
01640   if (!_dbus_connection_send_unlocked (connection, message, client_serial))
01641     {
01642       CONNECTION_UNLOCK (connection);
01643       return FALSE;
01644     }
01645 
01646   CONNECTION_UNLOCK (connection);
01647   return TRUE;
01648 }
01649 
01650 static dbus_bool_t
01651 reply_handler_timeout (void *data)
01652 {
01653   DBusConnection *connection;
01654   DBusDispatchStatus status;
01655   DBusPendingCall *pending = data;
01656 
01657   connection = pending->connection;
01658   
01659   CONNECTION_LOCK (connection);
01660   if (pending->timeout_link)
01661     {
01662       _dbus_connection_queue_synthesized_message_link (connection,
01663                                                        pending->timeout_link);
01664       pending->timeout_link = NULL;
01665     }
01666 
01667   _dbus_connection_remove_timeout (connection,
01668                                    pending->timeout);
01669   pending->timeout_added = FALSE;
01670 
01671   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01672 
01673   /* Unlocks, and calls out to user code */
01674   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01675   
01676   return TRUE;
01677 }
01678 
01716 dbus_bool_t
01717 dbus_connection_send_with_reply (DBusConnection     *connection,
01718                                  DBusMessage        *message,
01719                                  DBusPendingCall   **pending_return,
01720                                  int                 timeout_milliseconds)
01721 {
01722   DBusPendingCall *pending;
01723   DBusMessage *reply;
01724   DBusList *reply_link;
01725   dbus_int32_t serial = -1;
01726 
01727   _dbus_return_val_if_fail (connection != NULL, FALSE);
01728   _dbus_return_val_if_fail (message != NULL, FALSE);
01729   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01730 
01731   if (pending_return)
01732     *pending_return = NULL;
01733   
01734   pending = _dbus_pending_call_new (connection,
01735                                     timeout_milliseconds,
01736                                     reply_handler_timeout);
01737 
01738   if (pending == NULL)
01739     return FALSE;
01740 
01741   CONNECTION_LOCK (connection);
01742   
01743   /* Assign a serial to the message */
01744   if (dbus_message_get_serial (message) == 0)
01745     {
01746       serial = _dbus_connection_get_next_client_serial (connection);
01747       _dbus_message_set_serial (message, serial);
01748     }
01749 
01750   pending->reply_serial = serial;
01751 
01752   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
01753                                   "No reply within specified time");
01754   if (reply == NULL)
01755     goto error;
01756 
01757   reply_link = _dbus_list_alloc_link (reply);
01758   if (reply_link == NULL)
01759     {
01760       CONNECTION_UNLOCK (connection);
01761       dbus_message_unref (reply);
01762       goto error_unlocked;
01763     }
01764 
01765   pending->timeout_link = reply_link;
01766 
01767   /* Insert the serial in the pending replies hash;
01768    * hash takes a refcount on DBusPendingCall.
01769    * Also, add the timeout.
01770    */
01771   if (!_dbus_connection_attach_pending_call_unlocked (connection,
01772                                                       pending))
01773     goto error;
01774   
01775   if (!_dbus_connection_send_unlocked (connection, message, NULL))
01776     {
01777       _dbus_connection_detach_pending_call_and_unlock (connection,
01778                                                        pending);
01779       goto error_unlocked;
01780     }
01781 
01782   if (pending_return)
01783     *pending_return = pending;
01784   else
01785     dbus_pending_call_unref (pending);
01786 
01787   CONNECTION_UNLOCK (connection);
01788   
01789   return TRUE;
01790 
01791  error:
01792   CONNECTION_UNLOCK (connection);
01793  error_unlocked:
01794   dbus_pending_call_unref (pending);
01795   return FALSE;
01796 }
01797 
01798 static DBusMessage*
01799 check_for_reply_unlocked (DBusConnection *connection,
01800                           dbus_uint32_t   client_serial)
01801 {
01802   DBusList *link;
01803   
01804   link = _dbus_list_get_first_link (&connection->incoming_messages);
01805 
01806   while (link != NULL)
01807     {
01808       DBusMessage *reply = link->data;
01809 
01810       if (dbus_message_get_reply_serial (reply) == client_serial)
01811         {
01812           _dbus_list_remove_link (&connection->incoming_messages, link);
01813           connection->n_incoming  -= 1;
01814           return reply;
01815         }
01816       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
01817     }
01818 
01819   return NULL;
01820 }
01821 
01839 DBusMessage*
01840 _dbus_connection_block_for_reply (DBusConnection     *connection,
01841                                   dbus_uint32_t       client_serial,
01842                                   int                 timeout_milliseconds)
01843 {
01844   long start_tv_sec, start_tv_usec;
01845   long end_tv_sec, end_tv_usec;
01846   long tv_sec, tv_usec;
01847   DBusDispatchStatus status;
01848 
01849   _dbus_return_val_if_fail (connection != NULL, NULL);
01850   _dbus_return_val_if_fail (client_serial != 0, NULL);
01851   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01852   
01853   if (timeout_milliseconds == -1)
01854     timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
01855 
01856   /* it would probably seem logical to pass in _DBUS_INT_MAX
01857    * for infinite timeout, but then math below would get
01858    * all overflow-prone, so smack that down.
01859    */
01860   if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
01861     timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
01862   
01863   /* Flush message queue */
01864   dbus_connection_flush (connection);
01865 
01866   CONNECTION_LOCK (connection);
01867 
01868   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
01869   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
01870   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
01871   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
01872   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
01873 
01874   _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",
01875                  timeout_milliseconds,
01876                  client_serial,
01877                  start_tv_sec, start_tv_usec,
01878                  end_tv_sec, end_tv_usec);
01879   
01880   /* Now we wait... */
01881   /* THREAD TODO: This is busted. What if a dispatch() or pop_message
01882    * gets the message before we do?
01883    */
01884   /* always block at least once as we know we don't have the reply yet */
01885   _dbus_connection_do_iteration (connection,
01886                                  DBUS_ITERATION_DO_READING |
01887                                  DBUS_ITERATION_BLOCK,
01888                                  timeout_milliseconds);
01889 
01890  recheck_status:
01891 
01892   /* queue messages and get status */
01893   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01894 
01895   if (status == DBUS_DISPATCH_DATA_REMAINS)
01896     {
01897       DBusMessage *reply;
01898       
01899       reply = check_for_reply_unlocked (connection, client_serial);
01900       if (reply != NULL)
01901         {          
01902           status = _dbus_connection_get_dispatch_status_unlocked (connection);
01903 
01904           _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
01905 
01906           /* Unlocks, and calls out to user code */
01907           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01908           
01909           return reply;
01910         }
01911     }
01912   
01913   _dbus_get_current_time (&tv_sec, &tv_usec);
01914   
01915   if (!_dbus_connection_get_is_connected_unlocked (connection))
01916     return NULL;
01917   else if (tv_sec < start_tv_sec)
01918     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
01919   else if (connection->disconnect_message_link == NULL)
01920     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
01921   else if (tv_sec < end_tv_sec ||
01922            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
01923     {
01924       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
01925         (end_tv_usec - tv_usec) / 1000;
01926       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
01927       _dbus_assert (timeout_milliseconds >= 0);
01928       
01929       if (status == DBUS_DISPATCH_NEED_MEMORY)
01930         {
01931           /* Try sleeping a bit, as we aren't sure we need to block for reading,
01932            * we may already have a reply in the buffer and just can't process
01933            * it.
01934            */
01935           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
01936           
01937           if (timeout_milliseconds < 100)
01938             ; /* just busy loop */
01939           else if (timeout_milliseconds <= 1000)
01940             _dbus_sleep_milliseconds (timeout_milliseconds / 3);
01941           else
01942             _dbus_sleep_milliseconds (1000);
01943         }
01944       else
01945         {          
01946           /* block again, we don't have the reply buffered yet. */
01947           _dbus_connection_do_iteration (connection,
01948                                          DBUS_ITERATION_DO_READING |
01949                                          DBUS_ITERATION_BLOCK,
01950                                          timeout_milliseconds);
01951         }
01952 
01953       goto recheck_status;
01954     }
01955 
01956   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
01957                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
01958 
01959   /* unlocks and calls out to user code */
01960   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01961 
01962   return NULL;
01963 }
01964 
01987 DBusMessage *
01988 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
01989                                            DBusMessage        *message,
01990                                            int                 timeout_milliseconds,
01991                                            DBusError          *error)
01992 {
01993   dbus_uint32_t client_serial;
01994   DBusMessage *reply;
01995   
01996   _dbus_return_val_if_fail (connection != NULL, NULL);
01997   _dbus_return_val_if_fail (message != NULL, NULL);
01998   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);  
01999   _dbus_return_val_if_error_is_set (error, NULL);
02000   
02001   if (!dbus_connection_send (connection, message, &client_serial))
02002     {
02003       _DBUS_SET_OOM (error);
02004       return NULL;
02005     }
02006 
02007   reply = _dbus_connection_block_for_reply (connection,
02008                                             client_serial,
02009                                             timeout_milliseconds);
02010   
02011   if (reply == NULL)
02012     {
02013       if (dbus_connection_get_is_connected (connection))
02014         dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
02015       else
02016         dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
02017 
02018       return NULL;
02019     }
02020   else if (dbus_set_error_from_message (error, reply))
02021     {
02022       dbus_message_unref (reply);
02023       return NULL;
02024     }
02025   else
02026     return reply;
02027 }
02028 
02034 void
02035 dbus_connection_flush (DBusConnection *connection)
02036 {
02037   /* We have to specify DBUS_ITERATION_DO_READING here because
02038    * otherwise we could have two apps deadlock if they are both doing
02039    * a flush(), and the kernel buffers fill up. This could change the
02040    * dispatch status.
02041    */
02042   DBusDispatchStatus status;
02043 
02044   _dbus_return_if_fail (connection != NULL);
02045   
02046   CONNECTION_LOCK (connection);
02047   while (connection->n_outgoing > 0 &&
02048          _dbus_connection_get_is_connected_unlocked (connection))
02049     _dbus_connection_do_iteration (connection,
02050                                    DBUS_ITERATION_DO_READING |
02051                                    DBUS_ITERATION_DO_WRITING |
02052                                    DBUS_ITERATION_BLOCK,
02053                                    -1);
02054 
02055   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02056 
02057   /* Unlocks and calls out to user code */
02058   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02059 }
02060 
02061 /* Call with mutex held. Will drop it while waiting and re-acquire
02062  * before returning
02063  */
02064 static void
02065 _dbus_connection_wait_for_borrowed (DBusConnection *connection)
02066 {
02067   _dbus_assert (connection->message_borrowed != NULL);
02068 
02069   while (connection->message_borrowed != NULL)
02070     dbus_condvar_wait (connection->message_returned_cond, connection->mutex);
02071 }
02072 
02087 DBusMessage*
02088 dbus_connection_borrow_message  (DBusConnection *connection)
02089 {
02090   DBusMessage *message;
02091   DBusDispatchStatus status;
02092 
02093   _dbus_return_val_if_fail (connection != NULL, NULL);
02094   /* can't borrow during dispatch */
02095   _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL);
02096   
02097   /* this is called for the side effect that it queues
02098    * up any messages from the transport
02099    */
02100   status = dbus_connection_get_dispatch_status (connection);
02101   if (status != DBUS_DISPATCH_DATA_REMAINS)
02102     return NULL;
02103   
02104   CONNECTION_LOCK (connection);
02105 
02106   if (connection->message_borrowed != NULL)
02107     _dbus_connection_wait_for_borrowed (connection);
02108   
02109   message = _dbus_list_get_first (&connection->incoming_messages);
02110 
02111   if (message) 
02112     connection->message_borrowed = message;
02113   
02114   CONNECTION_UNLOCK (connection);
02115   return message;
02116 }
02117 
02125 void
02126 dbus_connection_return_message (DBusConnection *connection,
02127                                 DBusMessage    *message)
02128 {
02129   _dbus_return_if_fail (connection != NULL);
02130   _dbus_return_if_fail (message != NULL);
02131   /* can't borrow during dispatch */
02132   _dbus_return_if_fail (!connection->dispatch_acquired);
02133   
02134   CONNECTION_LOCK (connection);
02135   
02136   _dbus_assert (message == connection->message_borrowed);
02137   
02138   connection->message_borrowed = NULL;
02139   dbus_condvar_wake_all (connection->message_returned_cond);
02140   
02141   CONNECTION_UNLOCK (connection);
02142 }
02143 
02153 void
02154 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02155                                         DBusMessage    *message)
02156 {
02157   DBusMessage *pop_message;
02158 
02159   _dbus_return_if_fail (connection != NULL);
02160   _dbus_return_if_fail (message != NULL);
02161   /* can't borrow during dispatch */
02162   _dbus_return_if_fail (!connection->dispatch_acquired);
02163   
02164   CONNECTION_LOCK (connection);
02165  
02166   _dbus_assert (message == connection->message_borrowed);
02167 
02168   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
02169   _dbus_assert (message == pop_message);
02170   
02171   connection->n_incoming -= 1;
02172  
02173   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
02174                  message, connection->n_incoming);
02175  
02176   connection->message_borrowed = NULL;
02177   dbus_condvar_wake_all (connection->message_returned_cond);
02178   
02179   CONNECTION_UNLOCK (connection);
02180 }
02181 
02182 /* See dbus_connection_pop_message, but requires the caller to own
02183  * the lock before calling. May drop the lock while running.
02184  */
02185 static DBusList*
02186 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
02187 {
02188   if (connection->message_borrowed != NULL)
02189     _dbus_connection_wait_for_borrowed (connection);
02190   
02191   if (connection->n_incoming > 0)
02192     {
02193       DBusList *link;
02194 
02195       link = _dbus_list_pop_first_link (&connection->incoming_messages);
02196       connection->n_incoming -= 1;
02197 
02198       _dbus_verbose ("Message %p (%d %s '%s') removed from incoming queue %p, %d incoming\n",
02199                      link->data,
02200                      dbus_message_get_type (link->data),
02201                      dbus_message_get_interface (link->data) ?
02202                      dbus_message_get_interface (link->data) :
02203                      "no interface",
02204                      dbus_message_get_signature (link->data),
02205                      connection, connection->n_incoming);
02206 
02207       return link;
02208     }
02209   else
02210     return NULL;
02211 }
02212 
02213 /* See dbus_connection_pop_message, but requires the caller to own
02214  * the lock before calling. May drop the lock while running.
02215  */
02216 static DBusMessage*
02217 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
02218 {
02219   DBusList *link;
02220   
02221   link = _dbus_connection_pop_message_link_unlocked (connection);
02222 
02223   if (link != NULL)
02224     {
02225       DBusMessage *message;
02226       
02227       message = link->data;
02228       
02229       _dbus_list_free_link (link);
02230       
02231       return message;
02232     }
02233   else
02234     return NULL;
02235 }
02236 
02237 static void
02238 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
02239                                                 DBusList       *message_link)
02240 {
02241   _dbus_assert (message_link != NULL);
02242   /* You can't borrow a message while a link is outstanding */
02243   _dbus_assert (connection->message_borrowed == NULL);
02244 
02245   _dbus_list_prepend_link (&connection->incoming_messages,
02246                            message_link);
02247   connection->n_incoming += 1;
02248 
02249   _dbus_verbose ("Message %p (%d %s '%s') put back into queue %p, %d incoming\n",
02250                  message_link->data,
02251                  dbus_message_get_type (message_link->data),
02252                  dbus_message_get_interface (message_link->data) ?
02253                  dbus_message_get_interface (message_link->data) :
02254                  "no interface",
02255                  dbus_message_get_signature (message_link->data),
02256                  connection, connection->n_incoming);
02257 }
02258 
02273 DBusMessage*
02274 dbus_connection_pop_message (DBusConnection *connection)
02275 {
02276   DBusMessage *message;
02277   DBusDispatchStatus status;
02278 
02279   /* this is called for the side effect that it queues
02280    * up any messages from the transport
02281    */
02282   status = dbus_connection_get_dispatch_status (connection);
02283   if (status != DBUS_DISPATCH_DATA_REMAINS)
02284     return NULL;
02285   
02286   CONNECTION_LOCK (connection);
02287 
02288   message = _dbus_connection_pop_message_unlocked (connection);
02289 
02290   _dbus_verbose ("Returning popped message %p\n", message);    
02291   
02292   CONNECTION_UNLOCK (connection);
02293   
02294   return message;
02295 }
02296 
02305 static void
02306 _dbus_connection_acquire_dispatch (DBusConnection *connection)
02307 {
02308   if (connection->dispatch_acquired)
02309     dbus_condvar_wait (connection->dispatch_cond, connection->mutex);
02310   _dbus_assert (!connection->dispatch_acquired);
02311 
02312   connection->dispatch_acquired = TRUE;
02313 }
02314 
02322 static void
02323 _dbus_connection_release_dispatch (DBusConnection *connection)
02324 {
02325   _dbus_assert (connection->dispatch_acquired);
02326 
02327   connection->dispatch_acquired = FALSE;
02328   dbus_condvar_wake_one (connection->dispatch_cond);
02329 }
02330 
02331 static void
02332 _dbus_connection_failed_pop (DBusConnection *connection,
02333                              DBusList       *message_link)
02334 {
02335   _dbus_list_prepend_link (&connection->incoming_messages,
02336                            message_link);
02337   connection->n_incoming += 1;
02338 }
02339 
02340 static DBusDispatchStatus
02341 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
02342 {
02343   if (connection->n_incoming > 0)
02344     return DBUS_DISPATCH_DATA_REMAINS;
02345   else if (!_dbus_transport_queue_messages (connection->transport))
02346     return DBUS_DISPATCH_NEED_MEMORY;
02347   else
02348     {
02349       DBusDispatchStatus status;
02350       
02351       status = _dbus_transport_get_dispatch_status (connection->transport);
02352 
02353       if (status == DBUS_DISPATCH_COMPLETE &&
02354           connection->disconnect_message_link &&
02355           !_dbus_transport_get_is_connected (connection->transport))
02356         {
02357           /* We haven't sent the disconnect message already,
02358            * and all real messages have been queued up.
02359            */
02360           _dbus_connection_queue_synthesized_message_link (connection,
02361                                                            connection->disconnect_message_link);
02362           connection->disconnect_message_link = NULL;
02363         }
02364       
02365       if (status != DBUS_DISPATCH_COMPLETE)
02366         return status;
02367       else if (connection->n_incoming > 0)
02368         return DBUS_DISPATCH_DATA_REMAINS;
02369       else
02370         return DBUS_DISPATCH_COMPLETE;
02371     }
02372 }
02373 
02374 static void
02375 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
02376                                                     DBusDispatchStatus new_status)
02377 {
02378   dbus_bool_t changed;
02379   DBusDispatchStatusFunction function;
02380   void *data;
02381 
02382   /* We have the lock */
02383 
02384   _dbus_connection_ref_unlocked (connection);
02385 
02386   changed = new_status != connection->last_dispatch_status;
02387 
02388   connection->last_dispatch_status = new_status;
02389 
02390   function = connection->dispatch_status_function;
02391   data = connection->dispatch_status_data;
02392 
02393   /* We drop the lock */
02394   CONNECTION_UNLOCK (connection);
02395   
02396   if (changed && function)
02397     {
02398       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
02399                      connection, new_status,
02400                      new_status == DBUS_DISPATCH_COMPLETE ? "complete" :
02401                      new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" :
02402                      new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :
02403                      "???");
02404       (* function) (connection, new_status, data);      
02405     }
02406   
02407   dbus_connection_unref (connection);
02408 }
02409 
02418 DBusDispatchStatus
02419 dbus_connection_get_dispatch_status (DBusConnection *connection)
02420 {
02421   DBusDispatchStatus status;
02422 
02423   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02424   
02425   CONNECTION_LOCK (connection);
02426 
02427   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02428   
02429   CONNECTION_UNLOCK (connection);
02430 
02431   return status;
02432 }
02433 
02461 DBusDispatchStatus
02462 dbus_connection_dispatch (DBusConnection *connection)
02463 {
02464   DBusMessage *message;
02465   DBusList *link, *filter_list_copy, *message_link;
02466   DBusHandlerResult result;
02467   DBusPendingCall *pending;
02468   dbus_int32_t reply_serial;
02469   DBusDispatchStatus status;
02470 
02471   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02472 
02473   CONNECTION_LOCK (connection);
02474   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02475   if (status != DBUS_DISPATCH_DATA_REMAINS)
02476     {
02477       /* unlocks and calls out to user code */
02478       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02479       return status;
02480     }
02481   
02482   /* We need to ref the connection since the callback could potentially
02483    * drop the last ref to it
02484    */
02485   _dbus_connection_ref_unlocked (connection);
02486 
02487   _dbus_connection_acquire_dispatch (connection);
02488   
02489   /* This call may drop the lock during the execution (if waiting for
02490    * borrowed messages to be returned) but the order of message
02491    * dispatch if several threads call dispatch() is still
02492    * protected by the lock, since only one will get the lock, and that
02493    * one will finish the message dispatching
02494    */
02495   message_link = _dbus_connection_pop_message_link_unlocked (connection);
02496   if (message_link == NULL)
02497     {
02498       /* another thread dispatched our stuff */
02499 
02500       _dbus_connection_release_dispatch (connection);
02501 
02502       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02503 
02504       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02505       
02506       dbus_connection_unref (connection);
02507       
02508       return status;
02509     }
02510 
02511   message = message_link->data;
02512   
02513   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02514 
02515   reply_serial = dbus_message_get_reply_serial (message);
02516   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
02517                                          reply_serial);
02518   
02519   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
02520     {
02521       _dbus_connection_release_dispatch (connection);
02522 
02523       _dbus_connection_failed_pop (connection, message_link);
02524 
02525       /* unlocks and calls user code */
02526       _dbus_connection_update_dispatch_status_and_unlock (connection,
02527                                                           DBUS_DISPATCH_NEED_MEMORY);
02528 
02529       dbus_connection_unref (connection);
02530       
02531       return DBUS_DISPATCH_NEED_MEMORY;
02532     }
02533   
02534   _dbus_list_foreach (&filter_list_copy,
02535                       (DBusForeachFunction)_dbus_message_filter_ref,
02536                       NULL);
02537 
02538   /* We're still protected from dispatch() reentrancy here
02539    * since we acquired the dispatcher
02540    */
02541   CONNECTION_UNLOCK (connection);
02542   
02543   link = _dbus_list_get_first_link (&filter_list_copy);
02544   while (link != NULL)
02545     {
02546       DBusMessageFilter *filter = link->data;
02547       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
02548 
02549       _dbus_verbose ("  running filter on message %p\n", message);
02550       result = (* filter->function) (connection, message, filter->user_data);
02551 
02552       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02553         break;
02554 
02555       link = next;
02556     }
02557 
02558   _dbus_list_foreach (&filter_list_copy,
02559                       (DBusForeachFunction)_dbus_message_filter_unref,
02560                       NULL);
02561   _dbus_list_clear (&filter_list_copy);
02562   
02563   CONNECTION_LOCK (connection);
02564 
02565   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02566     goto out;
02567   
02568   /* Did a reply we were waiting on get filtered? */
02569   if (pending && result == DBUS_HANDLER_RESULT_HANDLED)
02570     {
02571       /* Queue the timeout immediately! */
02572       if (pending->timeout_link)
02573         {
02574           _dbus_connection_queue_synthesized_message_link (connection,
02575                                                            pending->timeout_link);
02576           pending->timeout_link = NULL;
02577         }
02578       else
02579         {
02580           /* We already queued the timeout? Then it was filtered! */
02581           _dbus_warn ("The timeout error with reply serial %d was filtered, so the DBusPendingCall will never stop pending.\n", reply_serial);
02582         }
02583     }
02584   
02585   if (result == DBUS_HANDLER_RESULT_HANDLED)
02586     goto out;
02587   
02588   if (pending)
02589     {
02590       _dbus_pending_call_complete_and_unlock (pending, message);
02591 
02592       pending = NULL;
02593       
02594       CONNECTION_LOCK (connection);
02595       goto out;
02596     }
02597 
02598   /* We're still protected from dispatch() reentrancy here
02599    * since we acquired the dispatcher
02600    */
02601   _dbus_verbose ("  running object path dispatch on message %p (%d %s '%s')\n",
02602                  message,
02603                  dbus_message_get_type (message),
02604                  dbus_message_get_interface (message) ?
02605                  dbus_message_get_interface (message) :
02606                  "no interface",
02607                  dbus_message_get_signature (message));
02608   
02609   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
02610                                                   message);
02611   
02612   CONNECTION_LOCK (connection);
02613 
02614   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02615     goto out;
02616 
02617   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
02618     {
02619       DBusMessage *reply;
02620       DBusString str;
02621       DBusPreallocatedSend *preallocated;
02622 
02623       _dbus_verbose ("  sending error %s\n",
02624                      DBUS_ERROR_UNKNOWN_METHOD);
02625       
02626       if (!_dbus_string_init (&str))
02627         {
02628           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02629           goto out;
02630         }
02631               
02632       if (!_dbus_string_append_printf (&str,
02633                                        "Method \"%s\" on interface \"%s\" doesn't exist\n",
02634                                        dbus_message_get_member (message),
02635                                        dbus_message_get_interface (message)))
02636         {
02637           _dbus_string_free (&str);
02638           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02639           goto out;
02640         }
02641       
02642       reply = dbus_message_new_error (message,
02643                                       DBUS_ERROR_UNKNOWN_METHOD,
02644                                       _dbus_string_get_const_data (&str));
02645       _dbus_string_free (&str);
02646 
02647       if (reply == NULL)
02648         {
02649           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02650           goto out;
02651         }
02652       
02653       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02654 
02655       if (preallocated == NULL)
02656         {
02657           dbus_message_unref (reply);
02658           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02659           goto out;
02660         }
02661 
02662       _dbus_connection_send_preallocated_unlocked (connection, preallocated,
02663                                                    reply, NULL);
02664 
02665       dbus_message_unref (reply);
02666       
02667       result = DBUS_HANDLER_RESULT_HANDLED;
02668     }
02669   
02670   _dbus_verbose ("  done dispatching %p (%d %s '%s') on connection %p\n", message,
02671                  dbus_message_get_type (message),
02672                  dbus_message_get_interface (message) ?
02673                  dbus_message_get_interface (message) :
02674                  "no interface",
02675                  dbus_message_get_signature (message),
02676                  connection);
02677   
02678  out:
02679   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02680     {
02681       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
02682       
02683       /* Put message back, and we'll start over.
02684        * Yes this means handlers must be idempotent if they
02685        * don't return HANDLED; c'est la vie.
02686        */
02687       _dbus_connection_putback_message_link_unlocked (connection,
02688                                                       message_link);
02689     }
02690   else
02691     {
02692       _dbus_verbose ("Done with message in %s\n", _DBUS_FUNCTION_NAME);
02693       
02694       if (connection->exit_on_disconnect &&
02695           dbus_message_is_signal (message,
02696                                   DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
02697                                   "Disconnected"))
02698         {
02699           _dbus_verbose ("Exiting on Disconnected signal\n");
02700           CONNECTION_UNLOCK (connection);
02701           _dbus_exit (1);
02702           _dbus_assert_not_reached ("Call to exit() returned");
02703         }
02704       
02705       _dbus_list_free_link (message_link);
02706       dbus_message_unref (message); /* don't want the message to count in max message limits
02707                                      * in computing dispatch status below
02708                                      */
02709     }
02710   
02711   _dbus_connection_release_dispatch (connection);
02712   
02713   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02714 
02715   /* unlocks and calls user code */
02716   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02717   
02718   dbus_connection_unref (connection);
02719   
02720   return status;
02721 }
02722 
02781 dbus_bool_t
02782 dbus_connection_set_watch_functions (DBusConnection              *connection,
02783                                      DBusAddWatchFunction         add_function,
02784                                      DBusRemoveWatchFunction      remove_function,
02785                                      DBusWatchToggledFunction     toggled_function,
02786                                      void                        *data,
02787                                      DBusFreeFunction             free_data_function)
02788 {
02789   dbus_bool_t retval;
02790 
02791   _dbus_return_val_if_fail (connection != NULL, FALSE);
02792   
02793   CONNECTION_LOCK (connection);
02794   /* ref connection for slightly better reentrancy */
02795   _dbus_connection_ref_unlocked (connection);
02796 
02797   /* FIXME this can call back into user code, and we need to drop the
02798    * connection lock when it does.
02799    */
02800   retval = _dbus_watch_list_set_functions (connection->watches,
02801                                            add_function, remove_function,
02802                                            toggled_function,
02803                                            data, free_data_function);
02804   
02805   CONNECTION_UNLOCK (connection);
02806   /* drop our paranoid refcount */
02807   dbus_connection_unref (connection);
02808 
02809   return retval;
02810 }
02811 
02845 dbus_bool_t
02846 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
02847                                          DBusAddTimeoutFunction     add_function,
02848                                          DBusRemoveTimeoutFunction  remove_function,
02849                                          DBusTimeoutToggledFunction toggled_function,
02850                                          void                      *data,
02851                                          DBusFreeFunction           free_data_function)
02852 {
02853   dbus_bool_t retval;
02854 
02855   _dbus_return_val_if_fail (connection != NULL, FALSE);
02856   
02857   CONNECTION_LOCK (connection);
02858   /* ref connection for slightly better reentrancy */
02859   _dbus_connection_ref_unlocked (connection);
02860   
02861   retval = _dbus_timeout_list_set_functions (connection->timeouts,
02862                                              add_function, remove_function,
02863                                              toggled_function,
02864                                              data, free_data_function);
02865   
02866   CONNECTION_UNLOCK (connection);
02867   /* drop our paranoid refcount */
02868   dbus_connection_unref (connection);
02869 
02870   return retval;
02871 }
02872 
02887 void
02888 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
02889                                           DBusWakeupMainFunction     wakeup_main_function,
02890                                           void                      *data,
02891                                           DBusFreeFunction           free_data_function)
02892 {
02893   void *old_data;
02894   DBusFreeFunction old_free_data;
02895 
02896   _dbus_return_if_fail (connection != NULL);
02897   
02898   CONNECTION_LOCK (connection);
02899   old_data = connection->wakeup_main_data;
02900   old_free_data = connection->free_wakeup_main_data;
02901 
02902   connection->wakeup_main_function = wakeup_main_function;
02903   connection->wakeup_main_data = data;
02904   connection->free_wakeup_main_data = free_data_function;
02905   
02906   CONNECTION_UNLOCK (connection);
02907 
02908   /* Callback outside the lock */
02909   if (old_free_data)
02910     (*old_free_data) (old_data);
02911 }
02912 
02929 void
02930 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
02931                                               DBusDispatchStatusFunction  function,
02932                                               void                       *data,
02933                                               DBusFreeFunction            free_data_function)
02934 {
02935   void *old_data;
02936   DBusFreeFunction old_free_data;
02937 
02938   _dbus_return_if_fail (connection != NULL);
02939   
02940   CONNECTION_LOCK (connection);
02941   old_data = connection->dispatch_status_data;
02942   old_free_data = connection->free_dispatch_status_data;
02943 
02944   connection->dispatch_status_function = function;
02945   connection->dispatch_status_data = data;
02946   connection->free_dispatch_status_data = free_data_function;
02947   
02948   CONNECTION_UNLOCK (connection);
02949 
02950   /* Callback outside the lock */
02951   if (old_free_data)
02952     (*old_free_data) (old_data);
02953 }
02954 
02967 dbus_bool_t
02968 dbus_connection_get_unix_fd (DBusConnection *connection,
02969                              int            *fd)
02970 {
02971   dbus_bool_t retval;
02972 
02973   _dbus_return_val_if_fail (connection != NULL, FALSE);
02974   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
02975   
02976   CONNECTION_LOCK (connection);
02977   
02978   retval = _dbus_transport_get_unix_fd (connection->transport,
02979                                         fd);
02980 
02981   CONNECTION_UNLOCK (connection);
02982 
02983   return retval;
02984 }
02985 
02997 dbus_bool_t
02998 dbus_connection_get_unix_user (DBusConnection *connection,
02999                                unsigned long  *uid)
03000 {
03001   dbus_bool_t result;
03002 
03003   _dbus_return_val_if_fail (connection != NULL, FALSE);
03004   _dbus_return_val_if_fail (uid != NULL, FALSE);
03005   
03006   CONNECTION_LOCK (connection);
03007 
03008   if (!_dbus_transport_get_is_authenticated (connection->transport))
03009     result = FALSE;
03010   else
03011     result = _dbus_transport_get_unix_user (connection->transport,
03012                                             uid);
03013   CONNECTION_UNLOCK (connection);
03014 
03015   return result;
03016 }
03017 
03028 dbus_bool_t
03029 dbus_connection_get_unix_process_id (DBusConnection *connection,
03030                                      unsigned long  *pid)
03031 {
03032   dbus_bool_t result;
03033 
03034   _dbus_return_val_if_fail (connection != NULL, FALSE);
03035   _dbus_return_val_if_fail (pid != NULL, FALSE);
03036   
03037   CONNECTION_LOCK (connection);
03038 
03039   if (!_dbus_transport_get_is_authenticated (connection->transport))
03040     result = FALSE;
03041   else
03042     result = _dbus_transport_get_unix_process_id (connection->transport,
03043                                                   pid);
03044   CONNECTION_UNLOCK (connection);
03045 
03046   return result;
03047 }
03048 
03065 void
03066 dbus_connection_set_unix_user_function (DBusConnection             *connection,
03067                                         DBusAllowUnixUserFunction   function,
03068                                         void                       *data,
03069                                         DBusFreeFunction            free_data_function)
03070 {
03071   void *old_data = NULL;
03072   DBusFreeFunction old_free_function = NULL;
03073 
03074   _dbus_return_if_fail (connection != NULL);
03075   
03076   CONNECTION_LOCK (connection);
03077   _dbus_transport_set_unix_user_function (connection->transport,
03078                                           function, data, free_data_function,
03079                                           &old_data, &old_free_function);
03080   CONNECTION_UNLOCK (connection);
03081 
03082   if (old_free_function != NULL)
03083     (* old_free_function) (old_data);    
03084 }
03085 
03107 dbus_bool_t
03108 dbus_connection_add_filter (DBusConnection            *connection,
03109                             DBusHandleMessageFunction  function,
03110                             void                      *user_data,
03111                             DBusFreeFunction           free_data_function)
03112 {
03113   DBusMessageFilter *filter;
03114   
03115   _dbus_return_val_if_fail (connection != NULL, FALSE);
03116   _dbus_return_val_if_fail (function != NULL, FALSE);
03117 
03118   filter = dbus_new0 (DBusMessageFilter, 1);
03119   if (filter == NULL)
03120     return FALSE;
03121 
03122   filter->refcount.value = 1;
03123   
03124   CONNECTION_LOCK (connection);
03125 
03126   if (!_dbus_list_append (&connection->filter_list,
03127                           filter))
03128     {
03129       _dbus_message_filter_unref (filter);
03130       CONNECTION_UNLOCK (connection);
03131       return FALSE;
03132     }
03133 
03134   /* Fill in filter after all memory allocated,
03135    * so we don't run the free_user_data_function
03136    * if the add_filter() fails
03137    */
03138   
03139   filter->function = function;
03140   filter->user_data = user_data;
03141   filter->free_user_data_function = free_data_function;
03142         
03143   CONNECTION_UNLOCK (connection);
03144   return TRUE;
03145 }
03146 
03159 void
03160 dbus_connection_remove_filter (DBusConnection            *connection,
03161                                DBusHandleMessageFunction  function,
03162                                void                      *user_data)
03163 {
03164   DBusList *link;
03165   DBusMessageFilter *filter;
03166   
03167   _dbus_return_if_fail (connection != NULL);
03168   _dbus_return_if_fail (function != NULL);
03169   
03170   CONNECTION_LOCK (connection);
03171 
03172   filter = NULL;
03173   
03174   link = _dbus_list_get_last_link (&connection->filter_list);
03175   while (link != NULL)
03176     {
03177       filter = link->data;
03178 
03179       if (filter->function == function &&
03180           filter->user_data == user_data)
03181         {
03182           _dbus_list_remove_link (&connection->filter_list, link);
03183           filter->function = NULL;
03184           
03185           break;
03186         }
03187         
03188       link = _dbus_list_get_prev_link (&connection->filter_list, link);
03189     }
03190   
03191   CONNECTION_UNLOCK (connection);
03192 
03193 #ifndef DBUS_DISABLE_CHECKS
03194   if (filter == NULL)
03195     {
03196       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
03197                   function, user_data);
03198       return;
03199     }
03200 #endif
03201   
03202   /* Call application code */
03203   if (filter->free_user_data_function)
03204     (* filter->free_user_data_function) (filter->user_data);
03205 
03206   filter->free_user_data_function = NULL;
03207   filter->user_data = NULL;
03208   
03209   _dbus_message_filter_unref (filter);
03210 }
03211 
03223 dbus_bool_t
03224 dbus_connection_register_object_path (DBusConnection              *connection,
03225                                       const char                  *path,
03226                                       const DBusObjectPathVTable  *vtable,
03227                                       void                        *user_data)
03228 {
03229   char **decomposed_path;
03230   dbus_bool_t retval;
03231   
03232   _dbus_return_val_if_fail (connection != NULL, FALSE);
03233   _dbus_return_val_if_fail (path != NULL, FALSE);
03234   _dbus_return_val_if_fail (path[0] == '/', FALSE);
03235   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03236 
03237   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
03238     return FALSE;
03239 
03240   CONNECTION_LOCK (connection);
03241 
03242   retval = _dbus_object_tree_register (connection->objects,
03243                                        FALSE,
03244                                        (const char **) decomposed_path, vtable,
03245                                        user_data);
03246 
03247   CONNECTION_UNLOCK (connection);
03248 
03249   dbus_free_string_array (decomposed_path);
03250 
03251   return retval;
03252 }
03253 
03266 dbus_bool_t
03267 dbus_connection_register_fallback (DBusConnection              *connection,
03268                                    const char                  *path,
03269                                    const DBusObjectPathVTable  *vtable,
03270                                    void                        *user_data)
03271 {
03272   char **decomposed_path;
03273   dbus_bool_t retval;
03274   
03275   _dbus_return_val_if_fail (connection != NULL, FALSE);
03276   _dbus_return_val_if_fail (path != NULL, FALSE);
03277   _dbus_return_val_if_fail (path[0] == '/', FALSE);
03278   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03279 
03280   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
03281     return FALSE;
03282 
03283   CONNECTION_LOCK (connection);
03284 
03285   retval = _dbus_object_tree_register (connection->objects,
03286                                        TRUE,
03287                                        (const char **) decomposed_path, vtable,
03288                                        user_data);
03289 
03290   CONNECTION_UNLOCK (connection);
03291 
03292   dbus_free_string_array (decomposed_path);
03293 
03294   return retval;
03295 }
03296 
03306 dbus_bool_t
03307 dbus_connection_unregister_object_path (DBusConnection              *connection,
03308                                         const char                  *path)
03309 {
03310   char **decomposed_path;
03311 
03312   _dbus_return_val_if_fail (connection != NULL, FALSE);
03313   _dbus_return_val_if_fail (path != NULL, FALSE);
03314   _dbus_return_val_if_fail (path[0] == '/', FALSE);
03315 
03316   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
03317       return FALSE;
03318 
03319   CONNECTION_LOCK (connection);
03320 
03321   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
03322 
03323   dbus_free_string_array (decomposed_path);
03324 
03325   return TRUE;
03326 }
03327 
03338 dbus_bool_t
03339 dbus_connection_list_registered (DBusConnection              *connection,
03340                                  const char                  *parent_path,
03341                                  char                      ***child_entries)
03342 {
03343   char **decomposed_path;
03344   dbus_bool_t retval;
03345   _dbus_return_val_if_fail (connection != NULL, FALSE);
03346   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
03347   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
03348   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
03349 
03350   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
03351     return FALSE;
03352 
03353   CONNECTION_LOCK (connection);
03354 
03355   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
03356                                                          (const char **) decomposed_path,
03357                                                          child_entries);
03358   dbus_free_string_array (decomposed_path);
03359 
03360   return retval;
03361 }
03362 
03363 static DBusDataSlotAllocator slot_allocator;
03364 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
03365 
03380 dbus_bool_t
03381 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
03382 {
03383   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03384                                           _DBUS_LOCK_NAME (connection_slots),
03385                                           slot_p);
03386 }
03387 
03399 void
03400 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
03401 {
03402   _dbus_return_if_fail (*slot_p >= 0);
03403   
03404   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03405 }
03406 
03420 dbus_bool_t
03421 dbus_connection_set_data (DBusConnection   *connection,
03422                           dbus_int32_t      slot,
03423                           void             *data,
03424                           DBusFreeFunction  free_data_func)
03425 {
03426   DBusFreeFunction old_free_func;
03427   void *old_data;
03428   dbus_bool_t retval;
03429 
03430   _dbus_return_val_if_fail (connection != NULL, FALSE);
03431   _dbus_return_val_if_fail (slot >= 0, FALSE);
03432   
03433   CONNECTION_LOCK (connection);
03434 
03435   retval = _dbus_data_slot_list_set (&slot_allocator,
03436                                      &connection->slot_list,
03437                                      slot, data, free_data_func,
03438                                      &old_free_func, &old_data);
03439   
03440   CONNECTION_UNLOCK (connection);
03441 
03442   if (retval)
03443     {
03444       /* Do the actual free outside the connection lock */
03445       if (old_free_func)
03446         (* old_free_func) (old_data);
03447     }
03448 
03449   return retval;
03450 }
03451 
03460 void*
03461 dbus_connection_get_data (DBusConnection   *connection,
03462                           dbus_int32_t      slot)
03463 {
03464   void *res;
03465 
03466   _dbus_return_val_if_fail (connection != NULL, NULL);
03467   
03468   CONNECTION_LOCK (connection);
03469 
03470   res = _dbus_data_slot_list_get (&slot_allocator,
03471                                   &connection->slot_list,
03472                                   slot);
03473   
03474   CONNECTION_UNLOCK (connection);
03475 
03476   return res;
03477 }
03478 
03485 void
03486 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
03487 {  
03488   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
03489 }
03490 
03499 void
03500 dbus_connection_set_max_message_size (DBusConnection *connection,
03501                                       long            size)
03502 {
03503   _dbus_return_if_fail (connection != NULL);
03504   
03505   CONNECTION_LOCK (connection);
03506   _dbus_transport_set_max_message_size (connection->transport,
03507                                         size);
03508   CONNECTION_UNLOCK (connection);
03509 }
03510 
03517 long
03518 dbus_connection_get_max_message_size (DBusConnection *connection)
03519 {
03520   long res;
03521 
03522   _dbus_return_val_if_fail (connection != NULL, 0);
03523   
03524   CONNECTION_LOCK (connection);
03525   res = _dbus_transport_get_max_message_size (connection->transport);
03526   CONNECTION_UNLOCK (connection);
03527   return res;
03528 }
03529 
03555 void
03556 dbus_connection_set_max_received_size (DBusConnection *connection,
03557                                        long            size)
03558 {
03559   _dbus_return_if_fail (connection != NULL);
03560   
03561   CONNECTION_LOCK (connection);
03562   _dbus_transport_set_max_received_size (connection->transport,
03563                                          size);
03564   CONNECTION_UNLOCK (connection);
03565 }
03566 
03573 long
03574 dbus_connection_get_max_received_size (DBusConnection *connection)
03575 {
03576   long res;
03577 
03578   _dbus_return_val_if_fail (connection != NULL, 0);
03579   
03580   CONNECTION_LOCK (connection);
03581   res = _dbus_transport_get_max_received_size (connection->transport);
03582   CONNECTION_UNLOCK (connection);
03583   return res;
03584 }
03585 
03596 long
03597 dbus_connection_get_outgoing_size (DBusConnection *connection)
03598 {
03599   long res;
03600 
03601   _dbus_return_val_if_fail (connection != NULL, 0);
03602   
03603   CONNECTION_LOCK (connection);
03604   res = _dbus_counter_get_value (connection->outgoing_counter);
03605   CONNECTION_UNLOCK (connection);
03606   return res;
03607 }
03608 

Generated on Sat Sep 25 19:17:11 2004 for D-BUS by  doxygen 1.3.8-20040913