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
00041 #if 0
00042 #define CONNECTION_LOCK(connection) do { \
00043 _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); \
00044 dbus_mutex_lock ((connection)->mutex); \
00045 } while (0)
00046 #define CONNECTION_UNLOCK(connection) do { \
00047 _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); \
00048 dbus_mutex_unlock ((connection)->mutex); \
00049 } while (0)
00050 #else
00051 #define CONNECTION_LOCK(connection) dbus_mutex_lock ((connection)->mutex)
00052 #define CONNECTION_UNLOCK(connection) dbus_mutex_unlock ((connection)->mutex)
00053 #endif
00054
00132 typedef struct DBusMessageFilter DBusMessageFilter;
00133
00137 struct DBusMessageFilter
00138 {
00139 DBusAtomic refcount;
00140 DBusHandleMessageFunction function;
00141 void *user_data;
00142 DBusFreeFunction free_user_data_function;
00143 };
00144
00145
00149 struct DBusPreallocatedSend
00150 {
00151 DBusConnection *connection;
00152 DBusList *queue_link;
00153 DBusList *counter_link;
00154 };
00155
00156 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00157
00161 struct DBusConnection
00162 {
00163 DBusAtomic refcount;
00165 DBusMutex *mutex;
00167 dbus_bool_t dispatch_acquired;
00168 DBusCondVar *dispatch_cond;
00170 dbus_bool_t io_path_acquired;
00171 DBusCondVar *io_path_cond;
00173 DBusList *outgoing_messages;
00174 DBusList *incoming_messages;
00176 DBusMessage *message_borrowed;
00177 DBusCondVar *message_returned_cond;
00179 int n_outgoing;
00180 int n_incoming;
00182 DBusCounter *outgoing_counter;
00184 DBusTransport *transport;
00185 DBusWatchList *watches;
00186 DBusTimeoutList *timeouts;
00188 DBusList *filter_list;
00190 DBusDataSlotList slot_list;
00192 DBusHashTable *pending_replies;
00194 dbus_uint32_t client_serial;
00195 DBusList *disconnect_message_link;
00197 DBusWakeupMainFunction wakeup_main_function;
00198 void *wakeup_main_data;
00199 DBusFreeFunction free_wakeup_main_data;
00201 DBusDispatchStatusFunction dispatch_status_function;
00202 void *dispatch_status_data;
00203 DBusFreeFunction free_dispatch_status_data;
00205 DBusDispatchStatus last_dispatch_status;
00207 DBusList *link_cache;
00210 DBusObjectTree *objects;
00212 unsigned int exit_on_disconnect : 1;
00213 };
00214
00215 static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
00216 DBusTimeout *timeout);
00217 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00218 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00219 DBusDispatchStatus new_status);
00220 static void _dbus_connection_last_unref (DBusConnection *connection);
00221
00222 static void
00223 _dbus_message_filter_ref (DBusMessageFilter *filter)
00224 {
00225 _dbus_assert (filter->refcount.value > 0);
00226 _dbus_atomic_inc (&filter->refcount);
00227 }
00228
00229 static void
00230 _dbus_message_filter_unref (DBusMessageFilter *filter)
00231 {
00232 _dbus_assert (filter->refcount.value > 0);
00233
00234 if (_dbus_atomic_dec (&filter->refcount) == 1)
00235 {
00236 if (filter->free_user_data_function)
00237 (* filter->free_user_data_function) (filter->user_data);
00238
00239 dbus_free (filter);
00240 }
00241 }
00242
00248 void
00249 _dbus_connection_lock (DBusConnection *connection)
00250 {
00251 CONNECTION_LOCK (connection);
00252 }
00253
00259 void
00260 _dbus_connection_unlock (DBusConnection *connection)
00261 {
00262 CONNECTION_UNLOCK (connection);
00263 }
00264
00272 static void
00273 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00274 {
00275 if (connection->wakeup_main_function)
00276 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00277 }
00278
00279 #ifdef DBUS_BUILD_TESTS
00280
00290 dbus_bool_t
00291 _dbus_connection_queue_received_message (DBusConnection *connection,
00292 DBusMessage *message)
00293 {
00294 DBusList *link;
00295
00296 link = _dbus_list_alloc_link (message);
00297 if (link == NULL)
00298 return FALSE;
00299
00300 dbus_message_ref (message);
00301 _dbus_connection_queue_received_message_link (connection, link);
00302
00303 return TRUE;
00304 }
00305 #endif
00306
00315 void
00316 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00317 DBusList *link)
00318 {
00319 DBusPendingCall *pending;
00320 dbus_int32_t reply_serial;
00321 DBusMessage *message;
00322
00323 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00324
00325 _dbus_list_append_link (&connection->incoming_messages,
00326 link);
00327 message = link->data;
00328
00329
00330 reply_serial = dbus_message_get_reply_serial (message);
00331 if (reply_serial != -1)
00332 {
00333 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00334 reply_serial);
00335 if (pending != NULL)
00336 {
00337 if (pending->timeout_added)
00338 _dbus_connection_remove_timeout_locked (connection,
00339 pending->timeout);
00340
00341 pending->timeout_added = FALSE;
00342 }
00343 }
00344
00345 connection->n_incoming += 1;
00346
00347 _dbus_connection_wakeup_mainloop (connection);
00348
00349 _dbus_verbose ("Message %p (%d %s '%s') added to incoming queue %p, %d incoming\n",
00350 message,
00351 dbus_message_get_type (message),
00352 dbus_message_get_interface (message) ?
00353 dbus_message_get_interface (message) :
00354 "no interface",
00355 dbus_message_get_signature (message),
00356 connection,
00357 connection->n_incoming);
00358 }
00359
00370 static void
00371 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00372 DBusList *link)
00373 {
00374 _dbus_list_append_link (&connection->incoming_messages, link);
00375
00376 connection->n_incoming += 1;
00377
00378 _dbus_connection_wakeup_mainloop (connection);
00379
00380 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00381 link->data, connection, connection->n_incoming);
00382 }
00383
00384
00391 dbus_bool_t
00392 _dbus_connection_have_messages_to_send (DBusConnection *connection)
00393 {
00394 return connection->outgoing_messages != NULL;
00395 }
00396
00404 DBusMessage*
00405 _dbus_connection_get_message_to_send (DBusConnection *connection)
00406 {
00407 return _dbus_list_get_last (&connection->outgoing_messages);
00408 }
00409
00418 void
00419 _dbus_connection_message_sent (DBusConnection *connection,
00420 DBusMessage *message)
00421 {
00422 DBusList *link;
00423
00424 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00425
00426 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00427 _dbus_assert (link != NULL);
00428 _dbus_assert (link->data == message);
00429
00430
00431 _dbus_list_unlink (&connection->outgoing_messages,
00432 link);
00433 _dbus_list_prepend_link (&connection->link_cache, link);
00434
00435 connection->n_outgoing -= 1;
00436
00437 _dbus_verbose ("Message %p (%d %s '%s') removed from outgoing queue %p, %d left to send\n",
00438 message,
00439 dbus_message_get_type (message),
00440 dbus_message_get_interface (message) ?
00441 dbus_message_get_interface (message) :
00442 "no interface",
00443 dbus_message_get_signature (message),
00444 connection, connection->n_outgoing);
00445
00446
00447 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00448 &link);
00449 _dbus_list_prepend_link (&connection->link_cache, link);
00450
00451 dbus_message_unref (message);
00452
00453 if (connection->n_outgoing == 0)
00454 _dbus_transport_messages_pending (connection->transport,
00455 connection->n_outgoing);
00456 }
00457
00468 dbus_bool_t
00469 _dbus_connection_add_watch (DBusConnection *connection,
00470 DBusWatch *watch)
00471 {
00472 if (connection->watches)
00473 return _dbus_watch_list_add_watch (connection->watches,
00474 watch);
00475 else
00476 return FALSE;
00477 }
00478
00487 void
00488 _dbus_connection_remove_watch (DBusConnection *connection,
00489 DBusWatch *watch)
00490 {
00491 if (connection->watches)
00492 _dbus_watch_list_remove_watch (connection->watches,
00493 watch);
00494 }
00495
00505 void
00506 _dbus_connection_toggle_watch (DBusConnection *connection,
00507 DBusWatch *watch,
00508 dbus_bool_t enabled)
00509 {
00510 if (connection->watches)
00511 _dbus_watch_list_toggle_watch (connection->watches,
00512 watch, enabled);
00513 }
00514
00526 dbus_bool_t
00527 _dbus_connection_add_timeout (DBusConnection *connection,
00528 DBusTimeout *timeout)
00529 {
00530 if (connection->timeouts)
00531 return _dbus_timeout_list_add_timeout (connection->timeouts,
00532 timeout);
00533 else
00534 return FALSE;
00535 }
00536
00545 void
00546 _dbus_connection_remove_timeout (DBusConnection *connection,
00547 DBusTimeout *timeout)
00548 {
00549 if (connection->timeouts)
00550 _dbus_timeout_list_remove_timeout (connection->timeouts,
00551 timeout);
00552 }
00553
00554 static void
00555 _dbus_connection_remove_timeout_locked (DBusConnection *connection,
00556 DBusTimeout *timeout)
00557 {
00558 CONNECTION_LOCK (connection);
00559 _dbus_connection_remove_timeout (connection, timeout);
00560 CONNECTION_UNLOCK (connection);
00561 }
00562
00572 void
00573 _dbus_connection_toggle_timeout (DBusConnection *connection,
00574 DBusTimeout *timeout,
00575 dbus_bool_t enabled)
00576 {
00577 if (connection->timeouts)
00578 _dbus_timeout_list_toggle_timeout (connection->timeouts,
00579 timeout, enabled);
00580 }
00581
00582 static dbus_bool_t
00583 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00584 DBusPendingCall *pending)
00585 {
00586 _dbus_assert (pending->reply_serial != 0);
00587
00588 if (!_dbus_connection_add_timeout (connection, pending->timeout))
00589 return FALSE;
00590
00591 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00592 pending->reply_serial,
00593 pending))
00594 {
00595 _dbus_connection_remove_timeout (connection, pending->timeout);
00596 return FALSE;
00597 }
00598
00599 pending->timeout_added = TRUE;
00600 pending->connection = connection;
00601
00602 dbus_pending_call_ref (pending);
00603
00604 return TRUE;
00605 }
00606
00607 static void
00608 free_pending_call_on_hash_removal (void *data)
00609 {
00610 DBusPendingCall *pending;
00611
00612 if (data == NULL)
00613 return;
00614
00615 pending = data;
00616
00617 if (pending->connection)
00618 {
00619 if (pending->timeout_added)
00620 {
00621 _dbus_connection_remove_timeout (pending->connection,
00622 pending->timeout);
00623 pending->timeout_added = FALSE;
00624 }
00625
00626 pending->connection = NULL;
00627
00628 dbus_pending_call_unref (pending);
00629 }
00630 }
00631
00632 static void
00633 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00634 DBusPendingCall *pending)
00635 {
00636
00637
00638
00639
00640 dbus_pending_call_ref (pending);
00641 _dbus_hash_table_remove_int (connection->pending_replies,
00642 pending->reply_serial);
00643 CONNECTION_UNLOCK (connection);
00644 dbus_pending_call_unref (pending);
00645 }
00646
00655 void
00656 _dbus_connection_remove_pending_call (DBusConnection *connection,
00657 DBusPendingCall *pending)
00658 {
00659 CONNECTION_LOCK (connection);
00660 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00661 }
00662
00671 void
00672 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00673 DBusMessage *message)
00674 {
00675 if (message == NULL)
00676 {
00677 message = pending->timeout_link->data;
00678 _dbus_list_clear (&pending->timeout_link);
00679 }
00680 else
00681 dbus_message_ref (message);
00682
00683 _dbus_verbose (" handing message %p (%s) to pending call serial %u\n",
00684 message,
00685 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00686 "method return" :
00687 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00688 "error" : "other type",
00689 pending->reply_serial);
00690
00691 _dbus_assert (pending->reply == NULL);
00692 _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00693 pending->reply = message;
00694
00695 dbus_pending_call_ref (pending);
00696 _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00697
00698
00699 _dbus_pending_call_notify (pending);
00700 dbus_pending_call_unref (pending);
00701 }
00702
00712 static dbus_bool_t
00713 _dbus_connection_acquire_io_path (DBusConnection *connection,
00714 int timeout_milliseconds)
00715 {
00716 dbus_bool_t res = TRUE;
00717
00718 if (connection->io_path_acquired)
00719 {
00720 if (timeout_milliseconds != -1)
00721 res = dbus_condvar_wait_timeout (connection->io_path_cond,
00722 connection->mutex,
00723 timeout_milliseconds);
00724 else
00725 dbus_condvar_wait (connection->io_path_cond, connection->mutex);
00726 }
00727
00728 if (res)
00729 {
00730 _dbus_assert (!connection->io_path_acquired);
00731
00732 connection->io_path_acquired = TRUE;
00733 }
00734
00735 return res;
00736 }
00737
00745 static void
00746 _dbus_connection_release_io_path (DBusConnection *connection)
00747 {
00748 _dbus_assert (connection->io_path_acquired);
00749
00750 connection->io_path_acquired = FALSE;
00751 dbus_condvar_wake_one (connection->io_path_cond);
00752 }
00753
00754
00781 void
00782 _dbus_connection_do_iteration (DBusConnection *connection,
00783 unsigned int flags,
00784 int timeout_milliseconds)
00785 {
00786 if (connection->n_outgoing == 0)
00787 flags &= ~DBUS_ITERATION_DO_WRITING;
00788
00789 if (_dbus_connection_acquire_io_path (connection,
00790 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
00791 {
00792 _dbus_transport_do_iteration (connection->transport,
00793 flags, timeout_milliseconds);
00794 _dbus_connection_release_io_path (connection);
00795 }
00796 }
00797
00807 DBusConnection*
00808 _dbus_connection_new_for_transport (DBusTransport *transport)
00809 {
00810 DBusConnection *connection;
00811 DBusWatchList *watch_list;
00812 DBusTimeoutList *timeout_list;
00813 DBusHashTable *pending_replies;
00814 DBusMutex *mutex;
00815 DBusCondVar *message_returned_cond;
00816 DBusCondVar *dispatch_cond;
00817 DBusCondVar *io_path_cond;
00818 DBusList *disconnect_link;
00819 DBusMessage *disconnect_message;
00820 DBusCounter *outgoing_counter;
00821 DBusObjectTree *objects;
00822
00823 watch_list = NULL;
00824 connection = NULL;
00825 pending_replies = NULL;
00826 timeout_list = NULL;
00827 mutex = NULL;
00828 message_returned_cond = NULL;
00829 dispatch_cond = NULL;
00830 io_path_cond = NULL;
00831 disconnect_link = NULL;
00832 disconnect_message = NULL;
00833 outgoing_counter = NULL;
00834 objects = NULL;
00835
00836 watch_list = _dbus_watch_list_new ();
00837 if (watch_list == NULL)
00838 goto error;
00839
00840 timeout_list = _dbus_timeout_list_new ();
00841 if (timeout_list == NULL)
00842 goto error;
00843
00844 pending_replies =
00845 _dbus_hash_table_new (DBUS_HASH_INT,
00846 NULL,
00847 (DBusFreeFunction)free_pending_call_on_hash_removal);
00848 if (pending_replies == NULL)
00849 goto error;
00850
00851 connection = dbus_new0 (DBusConnection, 1);
00852 if (connection == NULL)
00853 goto error;
00854
00855 mutex = dbus_mutex_new ();
00856 if (mutex == NULL)
00857 goto error;
00858
00859 message_returned_cond = dbus_condvar_new ();
00860 if (message_returned_cond == NULL)
00861 goto error;
00862
00863 dispatch_cond = dbus_condvar_new ();
00864 if (dispatch_cond == NULL)
00865 goto error;
00866
00867 io_path_cond = dbus_condvar_new ();
00868 if (io_path_cond == NULL)
00869 goto error;
00870
00871 disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL,
00872 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
00873 "Disconnected");
00874
00875 if (disconnect_message == NULL)
00876 goto error;
00877
00878 disconnect_link = _dbus_list_alloc_link (disconnect_message);
00879 if (disconnect_link == NULL)
00880 goto error;
00881
00882 outgoing_counter = _dbus_counter_new ();
00883 if (outgoing_counter == NULL)
00884 goto error;
00885
00886 objects = _dbus_object_tree_new (connection);
00887 if (objects == NULL)
00888 goto error;
00889
00890 if (_dbus_modify_sigpipe)
00891 _dbus_disable_sigpipe ();
00892
00893 connection->refcount.value = 1;
00894 connection->mutex = mutex;
00895 connection->dispatch_cond = dispatch_cond;
00896 connection->io_path_cond = io_path_cond;
00897 connection->message_returned_cond = message_returned_cond;
00898 connection->transport = transport;
00899 connection->watches = watch_list;
00900 connection->timeouts = timeout_list;
00901 connection->pending_replies = pending_replies;
00902 connection->outgoing_counter = outgoing_counter;
00903 connection->filter_list = NULL;
00904 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
00905 connection->objects = objects;
00906 connection->exit_on_disconnect = FALSE;
00907
00908 _dbus_data_slot_list_init (&connection->slot_list);
00909
00910 connection->client_serial = 1;
00911
00912 connection->disconnect_message_link = disconnect_link;
00913
00914 if (!_dbus_transport_set_connection (transport, connection))
00915 goto error;
00916
00917 _dbus_transport_ref (transport);
00918
00919 return connection;
00920
00921 error:
00922 if (disconnect_message != NULL)
00923 dbus_message_unref (disconnect_message);
00924
00925 if (disconnect_link != NULL)
00926 _dbus_list_free_link (disconnect_link);
00927
00928 if (io_path_cond != NULL)
00929 dbus_condvar_free (io_path_cond);
00930
00931 if (dispatch_cond != NULL)
00932 dbus_condvar_free (dispatch_cond);
00933
00934 if (message_returned_cond != NULL)
00935 dbus_condvar_free (message_returned_cond);
00936
00937 if (mutex != NULL)
00938 dbus_mutex_free (mutex);
00939
00940 if (connection != NULL)
00941 dbus_free (connection);
00942
00943 if (pending_replies)
00944 _dbus_hash_table_unref (pending_replies);
00945
00946 if (watch_list)
00947 _dbus_watch_list_free (watch_list);
00948
00949 if (timeout_list)
00950 _dbus_timeout_list_free (timeout_list);
00951
00952 if (outgoing_counter)
00953 _dbus_counter_unref (outgoing_counter);
00954
00955 if (objects)
00956 _dbus_object_tree_unref (objects);
00957
00958 return NULL;
00959 }
00960
00967 void
00968 _dbus_connection_ref_unlocked (DBusConnection *connection)
00969 {
00970 #ifdef DBUS_HAVE_ATOMIC_INT
00971 _dbus_atomic_inc (&connection->refcount);
00972 #else
00973 _dbus_assert (connection->refcount.value > 0);
00974 connection->refcount.value += 1;
00975 #endif
00976 }
00977
00984 void
00985 _dbus_connection_unref_unlocked (DBusConnection *connection)
00986 {
00987 dbus_bool_t last_unref;
00988
00989 _dbus_return_if_fail (connection != NULL);
00990
00991
00992
00993
00994
00995 #ifdef DBUS_HAVE_ATOMIC_INT
00996 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
00997 #else
00998 _dbus_assert (connection->refcount.value > 0);
00999
01000 connection->refcount.value -= 1;
01001 last_unref = (connection->refcount.value == 0);
01002 #if 0
01003 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01004 #endif
01005 #endif
01006
01007 if (last_unref)
01008 _dbus_connection_last_unref (connection);
01009 }
01010
01011 static dbus_uint32_t
01012 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01013 {
01014 int serial;
01015
01016 serial = connection->client_serial++;
01017
01018 if (connection->client_serial < 0)
01019 connection->client_serial = 1;
01020
01021 return serial;
01022 }
01023
01037 dbus_bool_t
01038 _dbus_connection_handle_watch (DBusWatch *watch,
01039 unsigned int condition,
01040 void *data)
01041 {
01042 DBusConnection *connection;
01043 dbus_bool_t retval;
01044 DBusDispatchStatus status;
01045
01046 connection = data;
01047
01048 CONNECTION_LOCK (connection);
01049 _dbus_connection_acquire_io_path (connection, -1);
01050 retval = _dbus_transport_handle_watch (connection->transport,
01051 watch, condition);
01052 _dbus_connection_release_io_path (connection);
01053
01054 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01055
01056
01057 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01058
01059 return retval;
01060 }
01061
01086 DBusConnection*
01087 dbus_connection_open (const char *address,
01088 DBusError *error)
01089 {
01090 DBusConnection *connection;
01091 DBusTransport *transport;
01092
01093 _dbus_return_val_if_fail (address != NULL, NULL);
01094 _dbus_return_val_if_error_is_set (error, NULL);
01095
01096 transport = _dbus_transport_open (address, error);
01097 if (transport == NULL)
01098 {
01099 _DBUS_ASSERT_ERROR_IS_SET (error);
01100 return NULL;
01101 }
01102
01103 connection = _dbus_connection_new_for_transport (transport);
01104
01105 _dbus_transport_unref (transport);
01106
01107 if (connection == NULL)
01108 {
01109 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01110 return NULL;
01111 }
01112
01113 return connection;
01114 }
01115
01121 void
01122 dbus_connection_ref (DBusConnection *connection)
01123 {
01124 _dbus_return_if_fail (connection != NULL);
01125
01126
01127
01128
01129
01130 #ifdef DBUS_HAVE_ATOMIC_INT
01131 _dbus_atomic_inc (&connection->refcount);
01132 #else
01133 CONNECTION_LOCK (connection);
01134 _dbus_assert (connection->refcount.value > 0);
01135
01136 connection->refcount.value += 1;
01137 CONNECTION_UNLOCK (connection);
01138 #endif
01139 }
01140
01141 static void
01142 free_outgoing_message (void *element,
01143 void *data)
01144 {
01145 DBusMessage *message = element;
01146 DBusConnection *connection = data;
01147
01148 _dbus_message_remove_size_counter (message,
01149 connection->outgoing_counter,
01150 NULL);
01151 dbus_message_unref (message);
01152 }
01153
01154
01155
01156
01157
01158 static void
01159 _dbus_connection_last_unref (DBusConnection *connection)
01160 {
01161 DBusList *link;
01162
01163 _dbus_verbose ("Finalizing connection %p\n", connection);
01164
01165 _dbus_assert (connection->refcount.value == 0);
01166
01167
01168
01169
01170 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01171
01172
01173 _dbus_object_tree_free_all_unlocked (connection->objects);
01174
01175 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01176 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01177 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01178
01179 _dbus_watch_list_free (connection->watches);
01180 connection->watches = NULL;
01181
01182 _dbus_timeout_list_free (connection->timeouts);
01183 connection->timeouts = NULL;
01184
01185 _dbus_data_slot_list_free (&connection->slot_list);
01186
01187 link = _dbus_list_get_first_link (&connection->filter_list);
01188 while (link != NULL)
01189 {
01190 DBusMessageFilter *filter = link->data;
01191 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01192
01193 filter->function = NULL;
01194 _dbus_message_filter_unref (filter);
01195 link->data = NULL;
01196
01197 link = next;
01198 }
01199 _dbus_list_clear (&connection->filter_list);
01200
01201
01202
01203 _dbus_object_tree_unref (connection->objects);
01204
01205 _dbus_hash_table_unref (connection->pending_replies);
01206 connection->pending_replies = NULL;
01207
01208 _dbus_list_clear (&connection->filter_list);
01209
01210 _dbus_list_foreach (&connection->outgoing_messages,
01211 free_outgoing_message,
01212 connection);
01213 _dbus_list_clear (&connection->outgoing_messages);
01214
01215 _dbus_list_foreach (&connection->incoming_messages,
01216 (DBusForeachFunction) dbus_message_unref,
01217 NULL);
01218 _dbus_list_clear (&connection->incoming_messages);
01219
01220 _dbus_counter_unref (connection->outgoing_counter);
01221
01222 _dbus_transport_unref (connection->transport);
01223
01224 if (connection->disconnect_message_link)
01225 {
01226 DBusMessage *message = connection->disconnect_message_link->data;
01227 dbus_message_unref (message);
01228 _dbus_list_free_link (connection->disconnect_message_link);
01229 }
01230
01231 _dbus_list_clear (&connection->link_cache);
01232
01233 dbus_condvar_free (connection->dispatch_cond);
01234 dbus_condvar_free (connection->io_path_cond);
01235 dbus_condvar_free (connection->message_returned_cond);
01236
01237 dbus_mutex_free (connection->mutex);
01238
01239 dbus_free (connection);
01240 }
01241
01253 void
01254 dbus_connection_unref (DBusConnection *connection)
01255 {
01256 dbus_bool_t last_unref;
01257
01258 _dbus_return_if_fail (connection != NULL);
01259
01260
01261
01262
01263
01264 #ifdef DBUS_HAVE_ATOMIC_INT
01265 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01266 #else
01267 CONNECTION_LOCK (connection);
01268
01269 _dbus_assert (connection->refcount.value > 0);
01270
01271 connection->refcount.value -= 1;
01272 last_unref = (connection->refcount.value == 0);
01273
01274 #if 0
01275 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01276 #endif
01277
01278 CONNECTION_UNLOCK (connection);
01279 #endif
01280
01281 if (last_unref)
01282 _dbus_connection_last_unref (connection);
01283 }
01284
01298 void
01299 dbus_connection_disconnect (DBusConnection *connection)
01300 {
01301 DBusDispatchStatus status;
01302
01303 _dbus_return_if_fail (connection != NULL);
01304
01305 CONNECTION_LOCK (connection);
01306 _dbus_transport_disconnect (connection->transport);
01307
01308 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01309
01310
01311 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01312 }
01313
01314 static dbus_bool_t
01315 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01316 {
01317 return _dbus_transport_get_is_connected (connection->transport);
01318 }
01319
01330 dbus_bool_t
01331 dbus_connection_get_is_connected (DBusConnection *connection)
01332 {
01333 dbus_bool_t res;
01334
01335 _dbus_return_val_if_fail (connection != NULL, FALSE);
01336
01337 CONNECTION_LOCK (connection);
01338 res = _dbus_connection_get_is_connected_unlocked (connection);
01339 CONNECTION_UNLOCK (connection);
01340
01341 return res;
01342 }
01343
01352 dbus_bool_t
01353 dbus_connection_get_is_authenticated (DBusConnection *connection)
01354 {
01355 dbus_bool_t res;
01356
01357 _dbus_return_val_if_fail (connection != NULL, FALSE);
01358
01359 CONNECTION_LOCK (connection);
01360 res = _dbus_transport_get_is_authenticated (connection->transport);
01361 CONNECTION_UNLOCK (connection);
01362
01363 return res;
01364 }
01365
01379 void
01380 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
01381 dbus_bool_t exit_on_disconnect)
01382 {
01383 _dbus_return_if_fail (connection != NULL);
01384
01385 CONNECTION_LOCK (connection);
01386 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
01387 CONNECTION_UNLOCK (connection);
01388 }
01389
01390 static DBusPreallocatedSend*
01391 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01392 {
01393 DBusPreallocatedSend *preallocated;
01394
01395 _dbus_return_val_if_fail (connection != NULL, NULL);
01396
01397 preallocated = dbus_new (DBusPreallocatedSend, 1);
01398 if (preallocated == NULL)
01399 return NULL;
01400
01401 if (connection->link_cache != NULL)
01402 {
01403 preallocated->queue_link =
01404 _dbus_list_pop_first_link (&connection->link_cache);
01405 preallocated->queue_link->data = NULL;
01406 }
01407 else
01408 {
01409 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01410 if (preallocated->queue_link == NULL)
01411 goto failed_0;
01412 }
01413
01414 if (connection->link_cache != NULL)
01415 {
01416 preallocated->counter_link =
01417 _dbus_list_pop_first_link (&connection->link_cache);
01418 preallocated->counter_link->data = connection->outgoing_counter;
01419 }
01420 else
01421 {
01422 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01423 if (preallocated->counter_link == NULL)
01424 goto failed_1;
01425 }
01426
01427 _dbus_counter_ref (preallocated->counter_link->data);
01428
01429 preallocated->connection = connection;
01430
01431 return preallocated;
01432
01433 failed_1:
01434 _dbus_list_free_link (preallocated->queue_link);
01435 failed_0:
01436 dbus_free (preallocated);
01437
01438 return NULL;
01439 }
01440
01450 DBusPreallocatedSend*
01451 dbus_connection_preallocate_send (DBusConnection *connection)
01452 {
01453 DBusPreallocatedSend *preallocated;
01454
01455 _dbus_return_val_if_fail (connection != NULL, NULL);
01456
01457 CONNECTION_LOCK (connection);
01458
01459 preallocated =
01460 _dbus_connection_preallocate_send_unlocked (connection);
01461
01462 CONNECTION_UNLOCK (connection);
01463
01464 return preallocated;
01465 }
01466
01476 void
01477 dbus_connection_free_preallocated_send (DBusConnection *connection,
01478 DBusPreallocatedSend *preallocated)
01479 {
01480 _dbus_return_if_fail (connection != NULL);
01481 _dbus_return_if_fail (preallocated != NULL);
01482 _dbus_return_if_fail (connection == preallocated->connection);
01483
01484 _dbus_list_free_link (preallocated->queue_link);
01485 _dbus_counter_unref (preallocated->counter_link->data);
01486 _dbus_list_free_link (preallocated->counter_link);
01487 dbus_free (preallocated);
01488 }
01489
01490 static void
01491 _dbus_connection_send_preallocated_unlocked (DBusConnection *connection,
01492 DBusPreallocatedSend *preallocated,
01493 DBusMessage *message,
01494 dbus_uint32_t *client_serial)
01495 {
01496 dbus_uint32_t serial;
01497
01498 preallocated->queue_link->data = message;
01499 _dbus_list_prepend_link (&connection->outgoing_messages,
01500 preallocated->queue_link);
01501
01502 _dbus_message_add_size_counter_link (message,
01503 preallocated->counter_link);
01504
01505 dbus_free (preallocated);
01506 preallocated = NULL;
01507
01508 dbus_message_ref (message);
01509
01510 connection->n_outgoing += 1;
01511
01512 _dbus_verbose ("Message %p (%d %s '%s') added to outgoing queue %p, %d pending to send\n",
01513 message,
01514 dbus_message_get_type (message),
01515 dbus_message_get_interface (message) ?
01516 dbus_message_get_interface (message) :
01517 "no interface",
01518 dbus_message_get_signature (message),
01519 connection,
01520 connection->n_outgoing);
01521
01522 if (dbus_message_get_serial (message) == 0)
01523 {
01524 serial = _dbus_connection_get_next_client_serial (connection);
01525 _dbus_message_set_serial (message, serial);
01526 if (client_serial)
01527 *client_serial = serial;
01528 }
01529 else
01530 {
01531 if (client_serial)
01532 *client_serial = dbus_message_get_serial (message);
01533 }
01534
01535 _dbus_message_lock (message);
01536
01537 if (connection->n_outgoing == 1)
01538 _dbus_transport_messages_pending (connection->transport,
01539 connection->n_outgoing);
01540
01541 _dbus_connection_wakeup_mainloop (connection);
01542 }
01543
01556 void
01557 dbus_connection_send_preallocated (DBusConnection *connection,
01558 DBusPreallocatedSend *preallocated,
01559 DBusMessage *message,
01560 dbus_uint32_t *client_serial)
01561 {
01562 _dbus_return_if_fail (connection != NULL);
01563 _dbus_return_if_fail (preallocated != NULL);
01564 _dbus_return_if_fail (message != NULL);
01565 _dbus_return_if_fail (preallocated->connection == connection);
01566 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
01567 (dbus_message_get_interface (message) != NULL &&
01568 dbus_message_get_member (message) != NULL));
01569 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
01570 (dbus_message_get_interface (message) != NULL &&
01571 dbus_message_get_member (message) != NULL));
01572
01573 CONNECTION_LOCK (connection);
01574 _dbus_connection_send_preallocated_unlocked (connection,
01575 preallocated,
01576 message, client_serial);
01577 CONNECTION_UNLOCK (connection);
01578 }
01579
01580 static dbus_bool_t
01581 _dbus_connection_send_unlocked (DBusConnection *connection,
01582 DBusMessage *message,
01583 dbus_uint32_t *client_serial)
01584 {
01585 DBusPreallocatedSend *preallocated;
01586
01587 _dbus_assert (connection != NULL);
01588 _dbus_assert (message != NULL);
01589
01590 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01591 if (preallocated == NULL)
01592 return FALSE;
01593
01594
01595 _dbus_connection_send_preallocated_unlocked (connection,
01596 preallocated,
01597 message,
01598 client_serial);
01599 return TRUE;
01600 }
01601
01620 dbus_bool_t
01621 dbus_connection_send (DBusConnection *connection,
01622 DBusMessage *message,
01623 dbus_uint32_t *client_serial)
01624 {
01625 _dbus_return_val_if_fail (connection != NULL, FALSE);
01626 _dbus_return_val_if_fail (message != NULL, FALSE);
01627
01628 CONNECTION_LOCK (connection);
01629
01630 if (!_dbus_connection_send_unlocked (connection, message, client_serial))
01631 {
01632 CONNECTION_UNLOCK (connection);
01633 return FALSE;
01634 }
01635
01636 CONNECTION_UNLOCK (connection);
01637 return TRUE;
01638 }
01639
01640 static dbus_bool_t
01641 reply_handler_timeout (void *data)
01642 {
01643 DBusConnection *connection;
01644 DBusDispatchStatus status;
01645 DBusPendingCall *pending = data;
01646
01647 connection = pending->connection;
01648
01649 CONNECTION_LOCK (connection);
01650 if (pending->timeout_link)
01651 {
01652 _dbus_connection_queue_synthesized_message_link (connection,
01653 pending->timeout_link);
01654 pending->timeout_link = NULL;
01655 }
01656
01657 _dbus_connection_remove_timeout (connection,
01658 pending->timeout);
01659 pending->timeout_added = FALSE;
01660
01661 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01662
01663
01664 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01665
01666 return TRUE;
01667 }
01668
01706 dbus_bool_t
01707 dbus_connection_send_with_reply (DBusConnection *connection,
01708 DBusMessage *message,
01709 DBusPendingCall **pending_return,
01710 int timeout_milliseconds)
01711 {
01712 DBusPendingCall *pending;
01713 DBusMessage *reply;
01714 DBusList *reply_link;
01715 dbus_int32_t serial = -1;
01716
01717 _dbus_return_val_if_fail (connection != NULL, FALSE);
01718 _dbus_return_val_if_fail (message != NULL, FALSE);
01719 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01720
01721 if (pending_return)
01722 *pending_return = NULL;
01723
01724 pending = _dbus_pending_call_new (connection,
01725 timeout_milliseconds,
01726 reply_handler_timeout);
01727
01728 if (pending == NULL)
01729 return FALSE;
01730
01731 CONNECTION_LOCK (connection);
01732
01733
01734 if (dbus_message_get_serial (message) == 0)
01735 {
01736 serial = _dbus_connection_get_next_client_serial (connection);
01737 _dbus_message_set_serial (message, serial);
01738 }
01739
01740 pending->reply_serial = serial;
01741
01742 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
01743 "No reply within specified time");
01744 if (!reply)
01745 {
01746 CONNECTION_UNLOCK (connection);
01747 dbus_pending_call_unref (pending);
01748 return FALSE;
01749 }
01750
01751 reply_link = _dbus_list_alloc_link (reply);
01752 if (!reply)
01753 {
01754 CONNECTION_UNLOCK (connection);
01755 dbus_message_unref (reply);
01756 dbus_pending_call_unref (pending);
01757 return FALSE;
01758 }
01759
01760 pending->timeout_link = reply_link;
01761
01762
01763
01764
01765
01766 if (!_dbus_connection_attach_pending_call_unlocked (connection,
01767 pending))
01768 {
01769 CONNECTION_UNLOCK (connection);
01770 dbus_pending_call_unref (pending);
01771 return FALSE;
01772 }
01773
01774 if (!_dbus_connection_send_unlocked (connection, message, NULL))
01775 {
01776 _dbus_connection_detach_pending_call_and_unlock (connection,
01777 pending);
01778 return FALSE;
01779 }
01780
01781 if (pending_return)
01782 {
01783 dbus_pending_call_ref (pending);
01784 *pending_return = pending;
01785 }
01786
01787 CONNECTION_UNLOCK (connection);
01788
01789 return TRUE;
01790 }
01791
01792 static DBusMessage*
01793 check_for_reply_unlocked (DBusConnection *connection,
01794 dbus_uint32_t client_serial)
01795 {
01796 DBusList *link;
01797
01798 link = _dbus_list_get_first_link (&connection->incoming_messages);
01799
01800 while (link != NULL)
01801 {
01802 DBusMessage *reply = link->data;
01803
01804 if (dbus_message_get_reply_serial (reply) == client_serial)
01805 {
01806 _dbus_list_remove_link (&connection->incoming_messages, link);
01807 connection->n_incoming -= 1;
01808 dbus_message_ref (reply);
01809 return reply;
01810 }
01811 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
01812 }
01813
01814 return NULL;
01815 }
01816
01834 DBusMessage*
01835 _dbus_connection_block_for_reply (DBusConnection *connection,
01836 dbus_uint32_t client_serial,
01837 int timeout_milliseconds)
01838 {
01839 long start_tv_sec, start_tv_usec;
01840 long end_tv_sec, end_tv_usec;
01841 long tv_sec, tv_usec;
01842 DBusDispatchStatus status;
01843
01844 _dbus_return_val_if_fail (connection != NULL, NULL);
01845 _dbus_return_val_if_fail (client_serial != 0, NULL);
01846 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01847
01848 if (timeout_milliseconds == -1)
01849 timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
01850
01851
01852
01853
01854
01855 if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
01856 timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
01857
01858
01859 dbus_connection_flush (connection);
01860
01861 CONNECTION_LOCK (connection);
01862
01863 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
01864 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
01865 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
01866 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
01867 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
01868
01869 _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",
01870 timeout_milliseconds,
01871 client_serial,
01872 start_tv_sec, start_tv_usec,
01873 end_tv_sec, end_tv_usec);
01874
01875
01876
01877
01878
01879
01880 _dbus_connection_do_iteration (connection,
01881 DBUS_ITERATION_DO_READING |
01882 DBUS_ITERATION_BLOCK,
01883 timeout_milliseconds);
01884
01885 recheck_status:
01886
01887
01888 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01889
01890 if (status == DBUS_DISPATCH_DATA_REMAINS)
01891 {
01892 DBusMessage *reply;
01893
01894 reply = check_for_reply_unlocked (connection, client_serial);
01895 if (reply != NULL)
01896 {
01897 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01898
01899 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
01900
01901
01902 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01903
01904 return reply;
01905 }
01906 }
01907
01908 _dbus_get_current_time (&tv_sec, &tv_usec);
01909
01910 if (tv_sec < start_tv_sec)
01911 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
01912 else if (connection->disconnect_message_link == NULL)
01913 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
01914 else if (tv_sec < end_tv_sec ||
01915 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
01916 {
01917 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
01918 (end_tv_usec - tv_usec) / 1000;
01919 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
01920 _dbus_assert (timeout_milliseconds >= 0);
01921
01922 if (status == DBUS_DISPATCH_NEED_MEMORY)
01923 {
01924
01925
01926
01927
01928 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
01929
01930 if (timeout_milliseconds < 100)
01931 ;
01932 else if (timeout_milliseconds <= 1000)
01933 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
01934 else
01935 _dbus_sleep_milliseconds (1000);
01936 }
01937 else
01938 {
01939
01940 _dbus_connection_do_iteration (connection,
01941 DBUS_ITERATION_DO_READING |
01942 DBUS_ITERATION_BLOCK,
01943 timeout_milliseconds);
01944 }
01945
01946 goto recheck_status;
01947 }
01948
01949 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
01950 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
01951
01952
01953 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01954
01955 return NULL;
01956 }
01957
01980 DBusMessage *
01981 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
01982 DBusMessage *message,
01983 int timeout_milliseconds,
01984 DBusError *error)
01985 {
01986 dbus_uint32_t client_serial;
01987 DBusMessage *reply;
01988
01989 _dbus_return_val_if_fail (connection != NULL, NULL);
01990 _dbus_return_val_if_fail (message != NULL, NULL);
01991 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01992 _dbus_return_val_if_error_is_set (error, NULL);
01993
01994 if (!dbus_connection_send (connection, message, &client_serial))
01995 {
01996 _DBUS_SET_OOM (error);
01997 return NULL;
01998 }
01999
02000 reply = _dbus_connection_block_for_reply (connection,
02001 client_serial,
02002 timeout_milliseconds);
02003
02004 if (reply == NULL)
02005 {
02006 if (dbus_connection_get_is_connected (connection))
02007 dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
02008 else
02009 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
02010
02011 return NULL;
02012 }
02013 else if (dbus_set_error_from_message (error, reply))
02014 {
02015 dbus_message_unref (reply);
02016 return NULL;
02017 }
02018 else
02019 return reply;
02020 }
02021
02027 void
02028 dbus_connection_flush (DBusConnection *connection)
02029 {
02030
02031
02032
02033
02034
02035 DBusDispatchStatus status;
02036
02037 _dbus_return_if_fail (connection != NULL);
02038
02039 CONNECTION_LOCK (connection);
02040 while (connection->n_outgoing > 0 &&
02041 _dbus_connection_get_is_connected_unlocked (connection))
02042 _dbus_connection_do_iteration (connection,
02043 DBUS_ITERATION_DO_READING |
02044 DBUS_ITERATION_DO_WRITING |
02045 DBUS_ITERATION_BLOCK,
02046 -1);
02047
02048 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02049
02050
02051 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02052 }
02053
02054
02055
02056
02057 static void
02058 _dbus_connection_wait_for_borrowed (DBusConnection *connection)
02059 {
02060 _dbus_assert (connection->message_borrowed != NULL);
02061
02062 while (connection->message_borrowed != NULL)
02063 dbus_condvar_wait (connection->message_returned_cond, connection->mutex);
02064 }
02065
02080 DBusMessage*
02081 dbus_connection_borrow_message (DBusConnection *connection)
02082 {
02083 DBusMessage *message;
02084 DBusDispatchStatus status;
02085
02086 _dbus_return_val_if_fail (connection != NULL, NULL);
02087
02088 _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL);
02089
02090
02091
02092
02093 status = dbus_connection_get_dispatch_status (connection);
02094 if (status != DBUS_DISPATCH_DATA_REMAINS)
02095 return NULL;
02096
02097 CONNECTION_LOCK (connection);
02098
02099 if (connection->message_borrowed != NULL)
02100 _dbus_connection_wait_for_borrowed (connection);
02101
02102 message = _dbus_list_get_first (&connection->incoming_messages);
02103
02104 if (message)
02105 connection->message_borrowed = message;
02106
02107 CONNECTION_UNLOCK (connection);
02108 return message;
02109 }
02110
02118 void
02119 dbus_connection_return_message (DBusConnection *connection,
02120 DBusMessage *message)
02121 {
02122 _dbus_return_if_fail (connection != NULL);
02123 _dbus_return_if_fail (message != NULL);
02124
02125 _dbus_return_if_fail (!connection->dispatch_acquired);
02126
02127 CONNECTION_LOCK (connection);
02128
02129 _dbus_assert (message == connection->message_borrowed);
02130
02131 connection->message_borrowed = NULL;
02132 dbus_condvar_wake_all (connection->message_returned_cond);
02133
02134 CONNECTION_UNLOCK (connection);
02135 }
02136
02146 void
02147 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02148 DBusMessage *message)
02149 {
02150 DBusMessage *pop_message;
02151
02152 _dbus_return_if_fail (connection != NULL);
02153 _dbus_return_if_fail (message != NULL);
02154
02155 _dbus_return_if_fail (!connection->dispatch_acquired);
02156
02157 CONNECTION_LOCK (connection);
02158
02159 _dbus_assert (message == connection->message_borrowed);
02160
02161 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
02162 _dbus_assert (message == pop_message);
02163
02164 connection->n_incoming -= 1;
02165
02166 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
02167 message, connection->n_incoming);
02168
02169 connection->message_borrowed = NULL;
02170 dbus_condvar_wake_all (connection->message_returned_cond);
02171
02172 CONNECTION_UNLOCK (connection);
02173 }
02174
02175
02176
02177
02178 static DBusList*
02179 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
02180 {
02181 if (connection->message_borrowed != NULL)
02182 _dbus_connection_wait_for_borrowed (connection);
02183
02184 if (connection->n_incoming > 0)
02185 {
02186 DBusList *link;
02187
02188 link = _dbus_list_pop_first_link (&connection->incoming_messages);
02189 connection->n_incoming -= 1;
02190
02191 _dbus_verbose ("Message %p (%d %s '%s') removed from incoming queue %p, %d incoming\n",
02192 link->data,
02193 dbus_message_get_type (link->data),
02194 dbus_message_get_interface (link->data) ?
02195 dbus_message_get_interface (link->data) :
02196 "no interface",
02197 dbus_message_get_signature (link->data),
02198 connection, connection->n_incoming);
02199
02200 return link;
02201 }
02202 else
02203 return NULL;
02204 }
02205
02206
02207
02208
02209 static DBusMessage*
02210 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
02211 {
02212 DBusList *link;
02213
02214 link = _dbus_connection_pop_message_link_unlocked (connection);
02215
02216 if (link != NULL)
02217 {
02218 DBusMessage *message;
02219
02220 message = link->data;
02221
02222 _dbus_list_free_link (link);
02223
02224 return message;
02225 }
02226 else
02227 return NULL;
02228 }
02229
02230 static void
02231 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
02232 DBusList *message_link)
02233 {
02234 _dbus_assert (message_link != NULL);
02235
02236 _dbus_assert (connection->message_borrowed == NULL);
02237
02238 _dbus_list_prepend_link (&connection->incoming_messages,
02239 message_link);
02240 connection->n_incoming += 1;
02241
02242 _dbus_verbose ("Message %p (%d %s '%s') put back into queue %p, %d incoming\n",
02243 message_link->data,
02244 dbus_message_get_type (message_link->data),
02245 dbus_message_get_interface (message_link->data) ?
02246 dbus_message_get_interface (message_link->data) :
02247 "no interface",
02248 dbus_message_get_signature (message_link->data),
02249 connection, connection->n_incoming);
02250 }
02251
02266 DBusMessage*
02267 dbus_connection_pop_message (DBusConnection *connection)
02268 {
02269 DBusMessage *message;
02270 DBusDispatchStatus status;
02271
02272
02273
02274
02275 status = dbus_connection_get_dispatch_status (connection);
02276 if (status != DBUS_DISPATCH_DATA_REMAINS)
02277 return NULL;
02278
02279 CONNECTION_LOCK (connection);
02280
02281 message = _dbus_connection_pop_message_unlocked (connection);
02282
02283 _dbus_verbose ("Returning popped message %p\n", message);
02284
02285 CONNECTION_UNLOCK (connection);
02286
02287 return message;
02288 }
02289
02298 static void
02299 _dbus_connection_acquire_dispatch (DBusConnection *connection)
02300 {
02301 if (connection->dispatch_acquired)
02302 dbus_condvar_wait (connection->dispatch_cond, connection->mutex);
02303 _dbus_assert (!connection->dispatch_acquired);
02304
02305 connection->dispatch_acquired = TRUE;
02306 }
02307
02315 static void
02316 _dbus_connection_release_dispatch (DBusConnection *connection)
02317 {
02318 _dbus_assert (connection->dispatch_acquired);
02319
02320 connection->dispatch_acquired = FALSE;
02321 dbus_condvar_wake_one (connection->dispatch_cond);
02322 }
02323
02324 static void
02325 _dbus_connection_failed_pop (DBusConnection *connection,
02326 DBusList *message_link)
02327 {
02328 _dbus_list_prepend_link (&connection->incoming_messages,
02329 message_link);
02330 connection->n_incoming += 1;
02331 }
02332
02333 static DBusDispatchStatus
02334 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
02335 {
02336 if (connection->n_incoming > 0)
02337 return DBUS_DISPATCH_DATA_REMAINS;
02338 else if (!_dbus_transport_queue_messages (connection->transport))
02339 return DBUS_DISPATCH_NEED_MEMORY;
02340 else
02341 {
02342 DBusDispatchStatus status;
02343
02344 status = _dbus_transport_get_dispatch_status (connection->transport);
02345
02346 if (status == DBUS_DISPATCH_COMPLETE &&
02347 connection->disconnect_message_link &&
02348 !_dbus_transport_get_is_connected (connection->transport))
02349 {
02350
02351
02352
02353 _dbus_connection_queue_synthesized_message_link (connection,
02354 connection->disconnect_message_link);
02355 connection->disconnect_message_link = NULL;
02356 }
02357
02358 if (status != DBUS_DISPATCH_COMPLETE)
02359 return status;
02360 else if (connection->n_incoming > 0)
02361 return DBUS_DISPATCH_DATA_REMAINS;
02362 else
02363 return DBUS_DISPATCH_COMPLETE;
02364 }
02365 }
02366
02367 static void
02368 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
02369 DBusDispatchStatus new_status)
02370 {
02371 dbus_bool_t changed;
02372 DBusDispatchStatusFunction function;
02373 void *data;
02374
02375
02376
02377 _dbus_connection_ref_unlocked (connection);
02378
02379 changed = new_status != connection->last_dispatch_status;
02380
02381 connection->last_dispatch_status = new_status;
02382
02383 function = connection->dispatch_status_function;
02384 data = connection->dispatch_status_data;
02385
02386
02387 CONNECTION_UNLOCK (connection);
02388
02389 if (changed && function)
02390 {
02391 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
02392 connection, new_status,
02393 new_status == DBUS_DISPATCH_COMPLETE ? "complete" :
02394 new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" :
02395 new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :
02396 "???");
02397 (* function) (connection, new_status, data);
02398 }
02399
02400 dbus_connection_unref (connection);
02401 }
02402
02411 DBusDispatchStatus
02412 dbus_connection_get_dispatch_status (DBusConnection *connection)
02413 {
02414 DBusDispatchStatus status;
02415
02416 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02417
02418 CONNECTION_LOCK (connection);
02419
02420 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02421
02422 CONNECTION_UNLOCK (connection);
02423
02424 return status;
02425 }
02426
02454 DBusDispatchStatus
02455 dbus_connection_dispatch (DBusConnection *connection)
02456 {
02457 DBusMessage *message;
02458 DBusList *link, *filter_list_copy, *message_link;
02459 DBusHandlerResult result;
02460 DBusPendingCall *pending;
02461 dbus_int32_t reply_serial;
02462 DBusDispatchStatus status;
02463
02464 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02465
02466 CONNECTION_LOCK (connection);
02467 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02468 if (status != DBUS_DISPATCH_DATA_REMAINS)
02469 {
02470
02471 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02472 return status;
02473 }
02474
02475
02476
02477
02478 _dbus_connection_ref_unlocked (connection);
02479
02480 _dbus_connection_acquire_dispatch (connection);
02481
02482
02483
02484
02485
02486
02487
02488 message_link = _dbus_connection_pop_message_link_unlocked (connection);
02489 if (message_link == NULL)
02490 {
02491
02492
02493 _dbus_connection_release_dispatch (connection);
02494
02495 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02496
02497 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02498
02499 dbus_connection_unref (connection);
02500
02501 return status;
02502 }
02503
02504 message = message_link->data;
02505
02506 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02507
02508 reply_serial = dbus_message_get_reply_serial (message);
02509 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
02510 reply_serial);
02511
02512 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
02513 {
02514 _dbus_connection_release_dispatch (connection);
02515
02516 _dbus_connection_failed_pop (connection, message_link);
02517
02518
02519 _dbus_connection_update_dispatch_status_and_unlock (connection,
02520 DBUS_DISPATCH_NEED_MEMORY);
02521
02522 dbus_connection_unref (connection);
02523
02524 return DBUS_DISPATCH_NEED_MEMORY;
02525 }
02526
02527 _dbus_list_foreach (&filter_list_copy,
02528 (DBusForeachFunction)_dbus_message_filter_ref,
02529 NULL);
02530
02531
02532
02533
02534 CONNECTION_UNLOCK (connection);
02535
02536 link = _dbus_list_get_first_link (&filter_list_copy);
02537 while (link != NULL)
02538 {
02539 DBusMessageFilter *filter = link->data;
02540 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
02541
02542 _dbus_verbose (" running filter on message %p\n", message);
02543 result = (* filter->function) (connection, message, filter->user_data);
02544
02545 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02546 break;
02547
02548 link = next;
02549 }
02550
02551 _dbus_list_foreach (&filter_list_copy,
02552 (DBusForeachFunction)_dbus_message_filter_unref,
02553 NULL);
02554 _dbus_list_clear (&filter_list_copy);
02555
02556 CONNECTION_LOCK (connection);
02557
02558 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02559 goto out;
02560
02561
02562 if (pending && result == DBUS_HANDLER_RESULT_HANDLED)
02563 {
02564
02565 if (pending->timeout_link)
02566 {
02567 _dbus_connection_queue_synthesized_message_link (connection,
02568 pending->timeout_link);
02569 pending->timeout_link = NULL;
02570 }
02571 else
02572 {
02573
02574 _dbus_warn ("The timeout error with reply serial %d was filtered, so the DBusPendingCall will never stop pending.\n", reply_serial);
02575 }
02576 }
02577
02578 if (result == DBUS_HANDLER_RESULT_HANDLED)
02579 goto out;
02580
02581 if (pending)
02582 {
02583 _dbus_pending_call_complete_and_unlock (pending, message);
02584
02585 pending = NULL;
02586
02587 CONNECTION_LOCK (connection);
02588 goto out;
02589 }
02590
02591
02592
02593
02594 _dbus_verbose (" running object path dispatch on message %p (%d %s '%s')\n",
02595 message,
02596 dbus_message_get_type (message),
02597 dbus_message_get_interface (message) ?
02598 dbus_message_get_interface (message) :
02599 "no interface",
02600 dbus_message_get_signature (message));
02601
02602 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
02603 message);
02604
02605 CONNECTION_LOCK (connection);
02606
02607 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02608 goto out;
02609
02610 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
02611 {
02612 DBusMessage *reply;
02613 DBusString str;
02614 DBusPreallocatedSend *preallocated;
02615
02616 _dbus_verbose (" sending error %s\n",
02617 DBUS_ERROR_UNKNOWN_METHOD);
02618
02619 if (!_dbus_string_init (&str))
02620 {
02621 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02622 goto out;
02623 }
02624
02625 if (!_dbus_string_append_printf (&str,
02626 "Method \"%s\" on interface \"%s\" doesn't exist\n",
02627 dbus_message_get_member (message),
02628 dbus_message_get_interface (message)))
02629 {
02630 _dbus_string_free (&str);
02631 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02632 goto out;
02633 }
02634
02635 reply = dbus_message_new_error (message,
02636 DBUS_ERROR_UNKNOWN_METHOD,
02637 _dbus_string_get_const_data (&str));
02638 _dbus_string_free (&str);
02639
02640 if (reply == NULL)
02641 {
02642 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02643 goto out;
02644 }
02645
02646 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02647
02648 if (preallocated == NULL)
02649 {
02650 dbus_message_unref (reply);
02651 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02652 goto out;
02653 }
02654
02655 _dbus_connection_send_preallocated_unlocked (connection, preallocated,
02656 reply, NULL);
02657
02658 dbus_message_unref (reply);
02659
02660 result = DBUS_HANDLER_RESULT_HANDLED;
02661 }
02662
02663 _dbus_verbose (" done dispatching %p (%d %s '%s') on connection %p\n", message,
02664 dbus_message_get_type (message),
02665 dbus_message_get_interface (message) ?
02666 dbus_message_get_interface (message) :
02667 "no interface",
02668 dbus_message_get_signature (message),
02669 connection);
02670
02671 out:
02672 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02673 {
02674 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
02675
02676
02677
02678
02679
02680 _dbus_connection_putback_message_link_unlocked (connection,
02681 message_link);
02682 }
02683 else
02684 {
02685 _dbus_verbose ("Done with message in %s\n", _DBUS_FUNCTION_NAME);
02686
02687 if (connection->exit_on_disconnect &&
02688 dbus_message_is_signal (message,
02689 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
02690 "Disconnected"))
02691 {
02692 _dbus_verbose ("Exiting on Disconnected signal\n");
02693 CONNECTION_UNLOCK (connection);
02694 _dbus_exit (1);
02695 _dbus_assert_not_reached ("Call to exit() returned");
02696 }
02697
02698 _dbus_list_free_link (message_link);
02699 dbus_message_unref (message);
02700
02701
02702 }
02703
02704 _dbus_connection_release_dispatch (connection);
02705
02706 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02707
02708
02709 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02710
02711 dbus_connection_unref (connection);
02712
02713 return status;
02714 }
02715
02774 dbus_bool_t
02775 dbus_connection_set_watch_functions (DBusConnection *connection,
02776 DBusAddWatchFunction add_function,
02777 DBusRemoveWatchFunction remove_function,
02778 DBusWatchToggledFunction toggled_function,
02779 void *data,
02780 DBusFreeFunction free_data_function)
02781 {
02782 dbus_bool_t retval;
02783
02784 _dbus_return_val_if_fail (connection != NULL, FALSE);
02785
02786 CONNECTION_LOCK (connection);
02787
02788 _dbus_connection_ref_unlocked (connection);
02789
02790
02791
02792
02793 retval = _dbus_watch_list_set_functions (connection->watches,
02794 add_function, remove_function,
02795 toggled_function,
02796 data, free_data_function);
02797
02798 CONNECTION_UNLOCK (connection);
02799
02800 dbus_connection_unref (connection);
02801
02802 return retval;
02803 }
02804
02838 dbus_bool_t
02839 dbus_connection_set_timeout_functions (DBusConnection *connection,
02840 DBusAddTimeoutFunction add_function,
02841 DBusRemoveTimeoutFunction remove_function,
02842 DBusTimeoutToggledFunction toggled_function,
02843 void *data,
02844 DBusFreeFunction free_data_function)
02845 {
02846 dbus_bool_t retval;
02847
02848 _dbus_return_val_if_fail (connection != NULL, FALSE);
02849
02850 CONNECTION_LOCK (connection);
02851
02852 _dbus_connection_ref_unlocked (connection);
02853
02854 retval = _dbus_timeout_list_set_functions (connection->timeouts,
02855 add_function, remove_function,
02856 toggled_function,
02857 data, free_data_function);
02858
02859 CONNECTION_UNLOCK (connection);
02860
02861 dbus_connection_unref (connection);
02862
02863 return retval;
02864 }
02865
02880 void
02881 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
02882 DBusWakeupMainFunction wakeup_main_function,
02883 void *data,
02884 DBusFreeFunction free_data_function)
02885 {
02886 void *old_data;
02887 DBusFreeFunction old_free_data;
02888
02889 _dbus_return_if_fail (connection != NULL);
02890
02891 CONNECTION_LOCK (connection);
02892 old_data = connection->wakeup_main_data;
02893 old_free_data = connection->free_wakeup_main_data;
02894
02895 connection->wakeup_main_function = wakeup_main_function;
02896 connection->wakeup_main_data = data;
02897 connection->free_wakeup_main_data = free_data_function;
02898
02899 CONNECTION_UNLOCK (connection);
02900
02901
02902 if (old_free_data)
02903 (*old_free_data) (old_data);
02904 }
02905
02922 void
02923 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
02924 DBusDispatchStatusFunction function,
02925 void *data,
02926 DBusFreeFunction free_data_function)
02927 {
02928 void *old_data;
02929 DBusFreeFunction old_free_data;
02930
02931 _dbus_return_if_fail (connection != NULL);
02932
02933 CONNECTION_LOCK (connection);
02934 old_data = connection->dispatch_status_data;
02935 old_free_data = connection->free_dispatch_status_data;
02936
02937 connection->dispatch_status_function = function;
02938 connection->dispatch_status_data = data;
02939 connection->free_dispatch_status_data = free_data_function;
02940
02941 CONNECTION_UNLOCK (connection);
02942
02943
02944 if (old_free_data)
02945 (*old_free_data) (old_data);
02946 }
02947
02959 dbus_bool_t
02960 dbus_connection_get_unix_user (DBusConnection *connection,
02961 unsigned long *uid)
02962 {
02963 dbus_bool_t result;
02964
02965 _dbus_return_val_if_fail (connection != NULL, FALSE);
02966 _dbus_return_val_if_fail (uid != NULL, FALSE);
02967
02968 CONNECTION_LOCK (connection);
02969
02970 if (!_dbus_transport_get_is_authenticated (connection->transport))
02971 result = FALSE;
02972 else
02973 result = _dbus_transport_get_unix_user (connection->transport,
02974 uid);
02975 CONNECTION_UNLOCK (connection);
02976
02977 return result;
02978 }
02979
02996 void
02997 dbus_connection_set_unix_user_function (DBusConnection *connection,
02998 DBusAllowUnixUserFunction function,
02999 void *data,
03000 DBusFreeFunction free_data_function)
03001 {
03002 void *old_data = NULL;
03003 DBusFreeFunction old_free_function = NULL;
03004
03005 _dbus_return_if_fail (connection != NULL);
03006
03007 CONNECTION_LOCK (connection);
03008 _dbus_transport_set_unix_user_function (connection->transport,
03009 function, data, free_data_function,
03010 &old_data, &old_free_function);
03011 CONNECTION_UNLOCK (connection);
03012
03013 if (old_free_function != NULL)
03014 (* old_free_function) (old_data);
03015 }
03016
03038 dbus_bool_t
03039 dbus_connection_add_filter (DBusConnection *connection,
03040 DBusHandleMessageFunction function,
03041 void *user_data,
03042 DBusFreeFunction free_data_function)
03043 {
03044 DBusMessageFilter *filter;
03045
03046 _dbus_return_val_if_fail (connection != NULL, FALSE);
03047 _dbus_return_val_if_fail (function != NULL, FALSE);
03048
03049 filter = dbus_new0 (DBusMessageFilter, 1);
03050 if (filter == NULL)
03051 return FALSE;
03052
03053 filter->refcount.value = 1;
03054
03055 CONNECTION_LOCK (connection);
03056
03057 if (!_dbus_list_append (&connection->filter_list,
03058 filter))
03059 {
03060 _dbus_message_filter_unref (filter);
03061 CONNECTION_UNLOCK (connection);
03062 return FALSE;
03063 }
03064
03065
03066
03067
03068
03069
03070 filter->function = function;
03071 filter->user_data = user_data;
03072 filter->free_user_data_function = free_data_function;
03073
03074 CONNECTION_UNLOCK (connection);
03075 return TRUE;
03076 }
03077
03090 void
03091 dbus_connection_remove_filter (DBusConnection *connection,
03092 DBusHandleMessageFunction function,
03093 void *user_data)
03094 {
03095 DBusList *link;
03096 DBusMessageFilter *filter;
03097
03098 _dbus_return_if_fail (connection != NULL);
03099 _dbus_return_if_fail (function != NULL);
03100
03101 CONNECTION_LOCK (connection);
03102
03103 filter = NULL;
03104
03105 link = _dbus_list_get_last_link (&connection->filter_list);
03106 while (link != NULL)
03107 {
03108 filter = link->data;
03109
03110 if (filter->function == function &&
03111 filter->user_data == user_data)
03112 {
03113 _dbus_list_remove_link (&connection->filter_list, link);
03114 filter->function = NULL;
03115
03116 break;
03117 }
03118
03119 link = _dbus_list_get_prev_link (&connection->filter_list, link);
03120 }
03121
03122 CONNECTION_UNLOCK (connection);
03123
03124 #ifndef DBUS_DISABLE_CHECKS
03125 if (filter == NULL)
03126 {
03127 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
03128 function, user_data);
03129 return;
03130 }
03131 #endif
03132
03133
03134 if (filter->free_user_data_function)
03135 (* filter->free_user_data_function) (filter->user_data);
03136
03137 filter->free_user_data_function = NULL;
03138 filter->user_data = NULL;
03139
03140 _dbus_message_filter_unref (filter);
03141 }
03142
03154 dbus_bool_t
03155 dbus_connection_register_object_path (DBusConnection *connection,
03156 const char **path,
03157 const DBusObjectPathVTable *vtable,
03158 void *user_data)
03159 {
03160 dbus_bool_t retval;
03161
03162 _dbus_return_val_if_fail (connection != NULL, FALSE);
03163 _dbus_return_val_if_fail (path != NULL, FALSE);
03164 _dbus_return_val_if_fail (path[0] != NULL, FALSE);
03165 _dbus_return_val_if_fail (vtable != NULL, FALSE);
03166
03167 CONNECTION_LOCK (connection);
03168
03169 retval = _dbus_object_tree_register (connection->objects,
03170 FALSE,
03171 path, vtable,
03172 user_data);
03173
03174 CONNECTION_UNLOCK (connection);
03175
03176 return retval;
03177 }
03178
03191 dbus_bool_t
03192 dbus_connection_register_fallback (DBusConnection *connection,
03193 const char **path,
03194 const DBusObjectPathVTable *vtable,
03195 void *user_data)
03196 {
03197 dbus_bool_t retval;
03198
03199 _dbus_return_val_if_fail (connection != NULL, FALSE);
03200 _dbus_return_val_if_fail (path != NULL, FALSE);
03201 _dbus_return_val_if_fail (path[0] != NULL, FALSE);
03202 _dbus_return_val_if_fail (vtable != NULL, FALSE);
03203
03204 CONNECTION_LOCK (connection);
03205
03206 retval = _dbus_object_tree_register (connection->objects,
03207 TRUE,
03208 path, vtable,
03209 user_data);
03210
03211 CONNECTION_UNLOCK (connection);
03212
03213 return retval;
03214 }
03215
03224 void
03225 dbus_connection_unregister_object_path (DBusConnection *connection,
03226 const char **path)
03227 {
03228 _dbus_return_if_fail (connection != NULL);
03229 _dbus_return_if_fail (path != NULL);
03230 _dbus_return_if_fail (path[0] != NULL);
03231
03232 CONNECTION_LOCK (connection);
03233
03234 return _dbus_object_tree_unregister_and_unlock (connection->objects,
03235 path);
03236 }
03237
03248 dbus_bool_t
03249 dbus_connection_list_registered (DBusConnection *connection,
03250 const char **parent_path,
03251 char ***child_entries)
03252 {
03253 _dbus_return_val_if_fail (connection != NULL, FALSE);
03254 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
03255 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
03256
03257 CONNECTION_LOCK (connection);
03258
03259 return _dbus_object_tree_list_registered_and_unlock (connection->objects,
03260 parent_path,
03261 child_entries);
03262 }
03263
03264 static DBusDataSlotAllocator slot_allocator;
03265 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
03266
03281 dbus_bool_t
03282 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
03283 {
03284 return _dbus_data_slot_allocator_alloc (&slot_allocator,
03285 _DBUS_LOCK_NAME (connection_slots),
03286 slot_p);
03287 }
03288
03300 void
03301 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
03302 {
03303 _dbus_return_if_fail (*slot_p >= 0);
03304
03305 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03306 }
03307
03321 dbus_bool_t
03322 dbus_connection_set_data (DBusConnection *connection,
03323 dbus_int32_t slot,
03324 void *data,
03325 DBusFreeFunction free_data_func)
03326 {
03327 DBusFreeFunction old_free_func;
03328 void *old_data;
03329 dbus_bool_t retval;
03330
03331 _dbus_return_val_if_fail (connection != NULL, FALSE);
03332 _dbus_return_val_if_fail (slot >= 0, FALSE);
03333
03334 CONNECTION_LOCK (connection);
03335
03336 retval = _dbus_data_slot_list_set (&slot_allocator,
03337 &connection->slot_list,
03338 slot, data, free_data_func,
03339 &old_free_func, &old_data);
03340
03341 CONNECTION_UNLOCK (connection);
03342
03343 if (retval)
03344 {
03345
03346 if (old_free_func)
03347 (* old_free_func) (old_data);
03348 }
03349
03350 return retval;
03351 }
03352
03361 void*
03362 dbus_connection_get_data (DBusConnection *connection,
03363 dbus_int32_t slot)
03364 {
03365 void *res;
03366
03367 _dbus_return_val_if_fail (connection != NULL, NULL);
03368
03369 CONNECTION_LOCK (connection);
03370
03371 res = _dbus_data_slot_list_get (&slot_allocator,
03372 &connection->slot_list,
03373 slot);
03374
03375 CONNECTION_UNLOCK (connection);
03376
03377 return res;
03378 }
03379
03386 void
03387 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
03388 {
03389 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
03390 }
03391
03400 void
03401 dbus_connection_set_max_message_size (DBusConnection *connection,
03402 long size)
03403 {
03404 _dbus_return_if_fail (connection != NULL);
03405
03406 CONNECTION_LOCK (connection);
03407 _dbus_transport_set_max_message_size (connection->transport,
03408 size);
03409 CONNECTION_UNLOCK (connection);
03410 }
03411
03418 long
03419 dbus_connection_get_max_message_size (DBusConnection *connection)
03420 {
03421 long res;
03422
03423 _dbus_return_val_if_fail (connection != NULL, 0);
03424
03425 CONNECTION_LOCK (connection);
03426 res = _dbus_transport_get_max_message_size (connection->transport);
03427 CONNECTION_UNLOCK (connection);
03428 return res;
03429 }
03430
03456 void
03457 dbus_connection_set_max_received_size (DBusConnection *connection,
03458 long size)
03459 {
03460 _dbus_return_if_fail (connection != NULL);
03461
03462 CONNECTION_LOCK (connection);
03463 _dbus_transport_set_max_received_size (connection->transport,
03464 size);
03465 CONNECTION_UNLOCK (connection);
03466 }
03467
03474 long
03475 dbus_connection_get_max_received_size (DBusConnection *connection)
03476 {
03477 long res;
03478
03479 _dbus_return_val_if_fail (connection != NULL, 0);
03480
03481 CONNECTION_LOCK (connection);
03482 res = _dbus_transport_get_max_received_size (connection->transport);
03483 CONNECTION_UNLOCK (connection);
03484 return res;
03485 }
03486
03497 long
03498 dbus_connection_get_outgoing_size (DBusConnection *connection)
03499 {
03500 long res;
03501
03502 _dbus_return_val_if_fail (connection != NULL, 0);
03503
03504 CONNECTION_LOCK (connection);
03505 res = _dbus_counter_get_value (connection->outgoing_counter);
03506 CONNECTION_UNLOCK (connection);
03507 return res;
03508 }
03509