00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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
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)
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)
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)
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)
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)
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)
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
00640
00641
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);
00699 _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00700
00701
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;
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
00998
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
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
01134
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
01164
01165
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
01177
01178
01179 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01180
01181
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);
01204 link->data = NULL;
01205
01206 link = next;
01207 }
01208 _dbus_list_clear (&connection->filter_list);
01209
01210
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
01270
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
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
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
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
01767
01768
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
01856
01857
01858
01859 if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
01860 timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
01861
01862
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
01880
01881
01882
01883
01884 _dbus_connection_do_iteration (connection,
01885 DBUS_ITERATION_DO_READING |
01886 DBUS_ITERATION_BLOCK,
01887 timeout_milliseconds);
01888
01889 recheck_status:
01890
01891
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
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
01931
01932
01933
01934 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
01935
01936 if (timeout_milliseconds < 100)
01937 ;
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
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
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
02037
02038
02039
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
02057 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02058 }
02059
02060
02061
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
02094 _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL);
02095
02096
02097
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
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
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
02182
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
02213
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
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
02279
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
02357
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
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
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
02477 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02478 return status;
02479 }
02480
02481
02482
02483
02484 _dbus_connection_ref_unlocked (connection);
02485
02486 _dbus_connection_acquire_dispatch (connection);
02487
02488
02489
02490
02491
02492
02493
02494 message_link = _dbus_connection_pop_message_link_unlocked (connection);
02495 if (message_link == NULL)
02496 {
02497
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
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
02538
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
02568 if (pending && result == DBUS_HANDLER_RESULT_HANDLED)
02569 {
02570
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
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
02598
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
02683
02684
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);
02706
02707
02708 }
02709
02710 _dbus_connection_release_dispatch (connection);
02711
02712 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02713
02714
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
02794 _dbus_connection_ref_unlocked (connection);
02795
02796
02797
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
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
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
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
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
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
03072
03073
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
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
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