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

Generated on Wed Jun 9 05:01:25 2004 for D-BUS by doxygen1.2.15