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-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-pending-call-internal.h"
00033 #include "dbus-list.h"
00034 #include "dbus-hash.h"
00035 #include "dbus-message-internal.h"
00036 #include "dbus-threads.h"
00037 #include "dbus-protocol.h"
00038 #include "dbus-dataslot.h"
00039 #include "dbus-string.h"
00040 #include "dbus-pending-call.h"
00041 #include "dbus-object-tree.h"
00042 #include "dbus-threads-internal.h"
00043 #include "dbus-bus.h"
00044
00045 #ifdef DBUS_DISABLE_CHECKS
00046 #define TOOK_LOCK_CHECK(connection)
00047 #define RELEASING_LOCK_CHECK(connection)
00048 #define HAVE_LOCK_CHECK(connection)
00049 #else
00050 #define TOOK_LOCK_CHECK(connection) do { \
00051 _dbus_assert (!(connection)->have_connection_lock); \
00052 (connection)->have_connection_lock = TRUE; \
00053 } while (0)
00054 #define RELEASING_LOCK_CHECK(connection) do { \
00055 _dbus_assert ((connection)->have_connection_lock); \
00056 (connection)->have_connection_lock = FALSE; \
00057 } while (0)
00058 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00059
00060 #endif
00061
00062 #define TRACE_LOCKS 1
00063
00064 #define CONNECTION_LOCK(connection) do { \
00065 if (TRACE_LOCKS) { _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00066 _dbus_mutex_lock ((connection)->mutex); \
00067 TOOK_LOCK_CHECK (connection); \
00068 } while (0)
00069
00070 #define CONNECTION_UNLOCK(connection) do { \
00071 if (TRACE_LOCKS) { _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00072 RELEASING_LOCK_CHECK (connection); \
00073 _dbus_mutex_unlock ((connection)->mutex); \
00074 } while (0)
00075
00076 #define DISPATCH_STATUS_NAME(s) \
00077 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00078 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00079 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00080 "???")
00081
00202 typedef struct DBusMessageFilter DBusMessageFilter;
00203
00207 struct DBusMessageFilter
00208 {
00209 DBusAtomic refcount;
00210 DBusHandleMessageFunction function;
00211 void *user_data;
00212 DBusFreeFunction free_user_data_function;
00213 };
00214
00215
00219 struct DBusPreallocatedSend
00220 {
00221 DBusConnection *connection;
00222 DBusList *queue_link;
00223 DBusList *counter_link;
00224 };
00225
00226 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00227
00231 struct DBusConnection
00232 {
00233 DBusAtomic refcount;
00235 DBusMutex *mutex;
00237 DBusMutex *dispatch_mutex;
00238 DBusCondVar *dispatch_cond;
00239 DBusMutex *io_path_mutex;
00240 DBusCondVar *io_path_cond;
00242 DBusList *outgoing_messages;
00243 DBusList *incoming_messages;
00245 DBusMessage *message_borrowed;
00249 int n_outgoing;
00250 int n_incoming;
00252 DBusCounter *outgoing_counter;
00254 DBusTransport *transport;
00255 DBusWatchList *watches;
00256 DBusTimeoutList *timeouts;
00258 DBusList *filter_list;
00260 DBusDataSlotList slot_list;
00262 DBusHashTable *pending_replies;
00264 dbus_uint32_t client_serial;
00265 DBusList *disconnect_message_link;
00267 DBusWakeupMainFunction wakeup_main_function;
00268 void *wakeup_main_data;
00269 DBusFreeFunction free_wakeup_main_data;
00271 DBusDispatchStatusFunction dispatch_status_function;
00272 void *dispatch_status_data;
00273 DBusFreeFunction free_dispatch_status_data;
00275 DBusDispatchStatus last_dispatch_status;
00277 DBusList *link_cache;
00280 DBusObjectTree *objects;
00282 char *server_guid;
00284
00285
00286
00287
00288 dbus_bool_t dispatch_acquired;
00289 dbus_bool_t io_path_acquired;
00291 unsigned int shareable : 1;
00293 unsigned int exit_on_disconnect : 1;
00295 unsigned int route_peer_messages : 1;
00297 unsigned int disconnected_message_arrived : 1;
00301 unsigned int disconnected_message_processed : 1;
00305 #ifndef DBUS_DISABLE_CHECKS
00306 unsigned int have_connection_lock : 1;
00307 #endif
00308
00309 #ifndef DBUS_DISABLE_CHECKS
00310 int generation;
00311 #endif
00312 };
00313
00314 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00315 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00316 DBusDispatchStatus new_status);
00317 static void _dbus_connection_last_unref (DBusConnection *connection);
00318 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00319 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00320 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00321 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
00322 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
00323
00324 static DBusMessageFilter *
00325 _dbus_message_filter_ref (DBusMessageFilter *filter)
00326 {
00327 _dbus_assert (filter->refcount.value > 0);
00328 _dbus_atomic_inc (&filter->refcount);
00329
00330 return filter;
00331 }
00332
00333 static void
00334 _dbus_message_filter_unref (DBusMessageFilter *filter)
00335 {
00336 _dbus_assert (filter->refcount.value > 0);
00337
00338 if (_dbus_atomic_dec (&filter->refcount) == 1)
00339 {
00340 if (filter->free_user_data_function)
00341 (* filter->free_user_data_function) (filter->user_data);
00342
00343 dbus_free (filter);
00344 }
00345 }
00346
00352 void
00353 _dbus_connection_lock (DBusConnection *connection)
00354 {
00355 CONNECTION_LOCK (connection);
00356 }
00357
00363 void
00364 _dbus_connection_unlock (DBusConnection *connection)
00365 {
00366 CONNECTION_UNLOCK (connection);
00367 }
00368
00376 static void
00377 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00378 {
00379 if (connection->wakeup_main_function)
00380 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00381 }
00382
00383 #ifdef DBUS_BUILD_TESTS
00384
00394 dbus_bool_t
00395 _dbus_connection_queue_received_message (DBusConnection *connection,
00396 DBusMessage *message)
00397 {
00398 DBusList *link;
00399
00400 link = _dbus_list_alloc_link (message);
00401 if (link == NULL)
00402 return FALSE;
00403
00404 dbus_message_ref (message);
00405 _dbus_connection_queue_received_message_link (connection, link);
00406
00407 return TRUE;
00408 }
00409
00422 void
00423 _dbus_connection_test_get_locks (DBusConnection *connection,
00424 DBusMutex **mutex_loc,
00425 DBusMutex **dispatch_mutex_loc,
00426 DBusMutex **io_path_mutex_loc,
00427 DBusCondVar **dispatch_cond_loc,
00428 DBusCondVar **io_path_cond_loc)
00429 {
00430 *mutex_loc = connection->mutex;
00431 *dispatch_mutex_loc = connection->dispatch_mutex;
00432 *io_path_mutex_loc = connection->io_path_mutex;
00433 *dispatch_cond_loc = connection->dispatch_cond;
00434 *io_path_cond_loc = connection->io_path_cond;
00435 }
00436 #endif
00437
00446 void
00447 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00448 DBusList *link)
00449 {
00450 DBusPendingCall *pending;
00451 dbus_int32_t reply_serial;
00452 DBusMessage *message;
00453
00454 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00455
00456 _dbus_list_append_link (&connection->incoming_messages,
00457 link);
00458 message = link->data;
00459
00460
00461 reply_serial = dbus_message_get_reply_serial (message);
00462 if (reply_serial != -1)
00463 {
00464 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00465 reply_serial);
00466 if (pending != NULL)
00467 {
00468 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00469 _dbus_connection_remove_timeout_unlocked (connection,
00470 _dbus_pending_call_get_timeout_unlocked (pending));
00471
00472 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00473 }
00474 }
00475
00476
00477
00478 connection->n_incoming += 1;
00479
00480 _dbus_connection_wakeup_mainloop (connection);
00481
00482 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00483 message,
00484 dbus_message_get_type (message),
00485 dbus_message_get_path (message) ?
00486 dbus_message_get_path (message) :
00487 "no path",
00488 dbus_message_get_interface (message) ?
00489 dbus_message_get_interface (message) :
00490 "no interface",
00491 dbus_message_get_member (message) ?
00492 dbus_message_get_member (message) :
00493 "no member",
00494 dbus_message_get_signature (message),
00495 dbus_message_get_reply_serial (message),
00496 connection,
00497 connection->n_incoming);}
00498
00507 void
00508 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00509 DBusList *link)
00510 {
00511 HAVE_LOCK_CHECK (connection);
00512
00513 _dbus_list_append_link (&connection->incoming_messages, link);
00514
00515 connection->n_incoming += 1;
00516
00517 _dbus_connection_wakeup_mainloop (connection);
00518
00519 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00520 link->data, connection, connection->n_incoming);
00521 }
00522
00523
00531 dbus_bool_t
00532 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00533 {
00534 HAVE_LOCK_CHECK (connection);
00535 return connection->outgoing_messages != NULL;
00536 }
00537
00547 dbus_bool_t
00548 dbus_connection_has_messages_to_send (DBusConnection *connection)
00549 {
00550 dbus_bool_t v;
00551
00552 _dbus_return_val_if_fail (connection != NULL, FALSE);
00553
00554 CONNECTION_LOCK (connection);
00555 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00556 CONNECTION_UNLOCK (connection);
00557
00558 return v;
00559 }
00560
00568 DBusMessage*
00569 _dbus_connection_get_message_to_send (DBusConnection *connection)
00570 {
00571 HAVE_LOCK_CHECK (connection);
00572
00573 return _dbus_list_get_last (&connection->outgoing_messages);
00574 }
00575
00584 void
00585 _dbus_connection_message_sent (DBusConnection *connection,
00586 DBusMessage *message)
00587 {
00588 DBusList *link;
00589
00590 HAVE_LOCK_CHECK (connection);
00591
00592
00593
00594
00595
00596
00597 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00598 _dbus_assert (link != NULL);
00599 _dbus_assert (link->data == message);
00600
00601
00602 _dbus_list_unlink (&connection->outgoing_messages,
00603 link);
00604 _dbus_list_prepend_link (&connection->link_cache, link);
00605
00606 connection->n_outgoing -= 1;
00607
00608 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00609 message,
00610 dbus_message_get_type (message),
00611 dbus_message_get_path (message) ?
00612 dbus_message_get_path (message) :
00613 "no path",
00614 dbus_message_get_interface (message) ?
00615 dbus_message_get_interface (message) :
00616 "no interface",
00617 dbus_message_get_member (message) ?
00618 dbus_message_get_member (message) :
00619 "no member",
00620 dbus_message_get_signature (message),
00621 connection, connection->n_outgoing);
00622
00623
00624 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00625 &link);
00626 _dbus_list_prepend_link (&connection->link_cache, link);
00627
00628 dbus_message_unref (message);
00629 }
00630
00632 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00633 DBusWatch *watch);
00635 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00636 DBusWatch *watch);
00638 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00639 DBusWatch *watch,
00640 dbus_bool_t enabled);
00641
00642 static dbus_bool_t
00643 protected_change_watch (DBusConnection *connection,
00644 DBusWatch *watch,
00645 DBusWatchAddFunction add_function,
00646 DBusWatchRemoveFunction remove_function,
00647 DBusWatchToggleFunction toggle_function,
00648 dbus_bool_t enabled)
00649 {
00650 DBusWatchList *watches;
00651 dbus_bool_t retval;
00652
00653 HAVE_LOCK_CHECK (connection);
00654
00655
00656
00657
00658
00659 watches = connection->watches;
00660 if (watches)
00661 {
00662 connection->watches = NULL;
00663 _dbus_connection_ref_unlocked (connection);
00664 CONNECTION_UNLOCK (connection);
00665
00666 if (add_function)
00667 retval = (* add_function) (watches, watch);
00668 else if (remove_function)
00669 {
00670 retval = TRUE;
00671 (* remove_function) (watches, watch);
00672 }
00673 else
00674 {
00675 retval = TRUE;
00676 (* toggle_function) (watches, watch, enabled);
00677 }
00678
00679 CONNECTION_LOCK (connection);
00680 connection->watches = watches;
00681 _dbus_connection_unref_unlocked (connection);
00682
00683 return retval;
00684 }
00685 else
00686 return FALSE;
00687 }
00688
00689
00701 dbus_bool_t
00702 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00703 DBusWatch *watch)
00704 {
00705 return protected_change_watch (connection, watch,
00706 _dbus_watch_list_add_watch,
00707 NULL, NULL, FALSE);
00708 }
00709
00719 void
00720 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00721 DBusWatch *watch)
00722 {
00723 protected_change_watch (connection, watch,
00724 NULL,
00725 _dbus_watch_list_remove_watch,
00726 NULL, FALSE);
00727 }
00728
00739 void
00740 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00741 DBusWatch *watch,
00742 dbus_bool_t enabled)
00743 {
00744 _dbus_assert (watch != NULL);
00745
00746 protected_change_watch (connection, watch,
00747 NULL, NULL,
00748 _dbus_watch_list_toggle_watch,
00749 enabled);
00750 }
00751
00753 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00754 DBusTimeout *timeout);
00756 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00757 DBusTimeout *timeout);
00759 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00760 DBusTimeout *timeout,
00761 dbus_bool_t enabled);
00762
00763 static dbus_bool_t
00764 protected_change_timeout (DBusConnection *connection,
00765 DBusTimeout *timeout,
00766 DBusTimeoutAddFunction add_function,
00767 DBusTimeoutRemoveFunction remove_function,
00768 DBusTimeoutToggleFunction toggle_function,
00769 dbus_bool_t enabled)
00770 {
00771 DBusTimeoutList *timeouts;
00772 dbus_bool_t retval;
00773
00774 HAVE_LOCK_CHECK (connection);
00775
00776
00777
00778
00779
00780 timeouts = connection->timeouts;
00781 if (timeouts)
00782 {
00783 connection->timeouts = NULL;
00784 _dbus_connection_ref_unlocked (connection);
00785 CONNECTION_UNLOCK (connection);
00786
00787 if (add_function)
00788 retval = (* add_function) (timeouts, timeout);
00789 else if (remove_function)
00790 {
00791 retval = TRUE;
00792 (* remove_function) (timeouts, timeout);
00793 }
00794 else
00795 {
00796 retval = TRUE;
00797 (* toggle_function) (timeouts, timeout, enabled);
00798 }
00799
00800 CONNECTION_LOCK (connection);
00801 connection->timeouts = timeouts;
00802 _dbus_connection_unref_unlocked (connection);
00803
00804 return retval;
00805 }
00806 else
00807 return FALSE;
00808 }
00809
00822 dbus_bool_t
00823 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00824 DBusTimeout *timeout)
00825 {
00826 return protected_change_timeout (connection, timeout,
00827 _dbus_timeout_list_add_timeout,
00828 NULL, NULL, FALSE);
00829 }
00830
00840 void
00841 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00842 DBusTimeout *timeout)
00843 {
00844 protected_change_timeout (connection, timeout,
00845 NULL,
00846 _dbus_timeout_list_remove_timeout,
00847 NULL, FALSE);
00848 }
00849
00860 void
00861 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00862 DBusTimeout *timeout,
00863 dbus_bool_t enabled)
00864 {
00865 protected_change_timeout (connection, timeout,
00866 NULL, NULL,
00867 _dbus_timeout_list_toggle_timeout,
00868 enabled);
00869 }
00870
00871 static dbus_bool_t
00872 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00873 DBusPendingCall *pending)
00874 {
00875 dbus_uint32_t reply_serial;
00876 DBusTimeout *timeout;
00877
00878 HAVE_LOCK_CHECK (connection);
00879
00880 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00881
00882 _dbus_assert (reply_serial != 0);
00883
00884 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00885
00886 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00887 return FALSE;
00888
00889 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00890 reply_serial,
00891 pending))
00892 {
00893 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00894
00895 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00896 HAVE_LOCK_CHECK (connection);
00897 return FALSE;
00898 }
00899
00900 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00901
00902 _dbus_pending_call_ref_unlocked (pending);
00903
00904 HAVE_LOCK_CHECK (connection);
00905
00906 return TRUE;
00907 }
00908
00909 static void
00910 free_pending_call_on_hash_removal (void *data)
00911 {
00912 DBusPendingCall *pending;
00913 DBusConnection *connection;
00914
00915 if (data == NULL)
00916 return;
00917
00918 pending = data;
00919
00920 connection = _dbus_pending_call_get_connection_unlocked (pending);
00921
00922 HAVE_LOCK_CHECK (connection);
00923
00924 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00925 {
00926 _dbus_connection_remove_timeout_unlocked (connection,
00927 _dbus_pending_call_get_timeout_unlocked (pending));
00928
00929 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00930 }
00931
00932
00933
00934
00935
00936
00937 _dbus_connection_ref_unlocked (connection);
00938 _dbus_pending_call_unref_and_unlock (pending);
00939 CONNECTION_LOCK (connection);
00940 _dbus_connection_unref_unlocked (connection);
00941 }
00942
00943 static void
00944 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00945 DBusPendingCall *pending)
00946 {
00947
00948
00949
00950 _dbus_hash_table_remove_int (connection->pending_replies,
00951 _dbus_pending_call_get_reply_serial_unlocked (pending));
00952 }
00953
00954 static void
00955 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00956 DBusPendingCall *pending)
00957 {
00958
00959
00960
00961
00962
00963
00964
00965 _dbus_pending_call_ref_unlocked (pending);
00966 _dbus_hash_table_remove_int (connection->pending_replies,
00967 _dbus_pending_call_get_reply_serial_unlocked (pending));
00968 _dbus_pending_call_unref_and_unlock (pending);
00969 }
00970
00979 void
00980 _dbus_connection_remove_pending_call (DBusConnection *connection,
00981 DBusPendingCall *pending)
00982 {
00983 CONNECTION_LOCK (connection);
00984 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00985 }
00986
00996 static dbus_bool_t
00997 _dbus_connection_acquire_io_path (DBusConnection *connection,
00998 int timeout_milliseconds)
00999 {
01000 dbus_bool_t we_acquired;
01001
01002 HAVE_LOCK_CHECK (connection);
01003
01004
01005 _dbus_connection_ref_unlocked (connection);
01006
01007
01008 CONNECTION_UNLOCK (connection);
01009
01010 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01011 _dbus_mutex_lock (connection->io_path_mutex);
01012
01013 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01014 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01015
01016 we_acquired = FALSE;
01017
01018 if (connection->io_path_acquired)
01019 {
01020 if (timeout_milliseconds != -1)
01021 {
01022 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01023 _DBUS_FUNCTION_NAME, timeout_milliseconds);
01024
01025 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01026 connection->io_path_mutex,
01027 timeout_milliseconds))
01028 {
01029
01030
01031
01032
01033
01034
01035
01036
01037 }
01038 }
01039 else
01040 {
01041 while (connection->io_path_acquired)
01042 {
01043 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01044 _dbus_condvar_wait (connection->io_path_cond,
01045 connection->io_path_mutex);
01046 }
01047 }
01048 }
01049
01050 if (!connection->io_path_acquired)
01051 {
01052 we_acquired = TRUE;
01053 connection->io_path_acquired = TRUE;
01054 }
01055
01056 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01057 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01058
01059 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01060 _dbus_mutex_unlock (connection->io_path_mutex);
01061
01062 CONNECTION_LOCK (connection);
01063
01064 HAVE_LOCK_CHECK (connection);
01065
01066 _dbus_connection_unref_unlocked (connection);
01067
01068 return we_acquired;
01069 }
01070
01078 static void
01079 _dbus_connection_release_io_path (DBusConnection *connection)
01080 {
01081 HAVE_LOCK_CHECK (connection);
01082
01083 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01084 _dbus_mutex_lock (connection->io_path_mutex);
01085
01086 _dbus_assert (connection->io_path_acquired);
01087
01088 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01089 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01090
01091 connection->io_path_acquired = FALSE;
01092 _dbus_condvar_wake_one (connection->io_path_cond);
01093
01094 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01095 _dbus_mutex_unlock (connection->io_path_mutex);
01096 }
01097
01126 void
01127 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01128 unsigned int flags,
01129 int timeout_milliseconds)
01130 {
01131 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01132
01133 HAVE_LOCK_CHECK (connection);
01134
01135 if (connection->n_outgoing == 0)
01136 flags &= ~DBUS_ITERATION_DO_WRITING;
01137
01138 if (_dbus_connection_acquire_io_path (connection,
01139 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01140 {
01141 HAVE_LOCK_CHECK (connection);
01142
01143 _dbus_transport_do_iteration (connection->transport,
01144 flags, timeout_milliseconds);
01145 _dbus_connection_release_io_path (connection);
01146 }
01147
01148 HAVE_LOCK_CHECK (connection);
01149
01150 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01151 }
01152
01162 DBusConnection*
01163 _dbus_connection_new_for_transport (DBusTransport *transport)
01164 {
01165 DBusConnection *connection;
01166 DBusWatchList *watch_list;
01167 DBusTimeoutList *timeout_list;
01168 DBusHashTable *pending_replies;
01169 DBusList *disconnect_link;
01170 DBusMessage *disconnect_message;
01171 DBusCounter *outgoing_counter;
01172 DBusObjectTree *objects;
01173
01174 watch_list = NULL;
01175 connection = NULL;
01176 pending_replies = NULL;
01177 timeout_list = NULL;
01178 disconnect_link = NULL;
01179 disconnect_message = NULL;
01180 outgoing_counter = NULL;
01181 objects = NULL;
01182
01183 watch_list = _dbus_watch_list_new ();
01184 if (watch_list == NULL)
01185 goto error;
01186
01187 timeout_list = _dbus_timeout_list_new ();
01188 if (timeout_list == NULL)
01189 goto error;
01190
01191 pending_replies =
01192 _dbus_hash_table_new (DBUS_HASH_INT,
01193 NULL,
01194 (DBusFreeFunction)free_pending_call_on_hash_removal);
01195 if (pending_replies == NULL)
01196 goto error;
01197
01198 connection = dbus_new0 (DBusConnection, 1);
01199 if (connection == NULL)
01200 goto error;
01201
01202 _dbus_mutex_new_at_location (&connection->mutex);
01203 if (connection->mutex == NULL)
01204 goto error;
01205
01206 _dbus_mutex_new_at_location (&connection->io_path_mutex);
01207 if (connection->io_path_mutex == NULL)
01208 goto error;
01209
01210 _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01211 if (connection->dispatch_mutex == NULL)
01212 goto error;
01213
01214 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01215 if (connection->dispatch_cond == NULL)
01216 goto error;
01217
01218 _dbus_condvar_new_at_location (&connection->io_path_cond);
01219 if (connection->io_path_cond == NULL)
01220 goto error;
01221
01222 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01223 DBUS_INTERFACE_LOCAL,
01224 "Disconnected");
01225
01226 if (disconnect_message == NULL)
01227 goto error;
01228
01229 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01230 if (disconnect_link == NULL)
01231 goto error;
01232
01233 outgoing_counter = _dbus_counter_new ();
01234 if (outgoing_counter == NULL)
01235 goto error;
01236
01237 objects = _dbus_object_tree_new (connection);
01238 if (objects == NULL)
01239 goto error;
01240
01241 if (_dbus_modify_sigpipe)
01242 _dbus_disable_sigpipe ();
01243
01244 connection->refcount.value = 1;
01245 connection->transport = transport;
01246 connection->watches = watch_list;
01247 connection->timeouts = timeout_list;
01248 connection->pending_replies = pending_replies;
01249 connection->outgoing_counter = outgoing_counter;
01250 connection->filter_list = NULL;
01251 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01252 connection->objects = objects;
01253 connection->exit_on_disconnect = FALSE;
01254 connection->shareable = FALSE;
01255 connection->route_peer_messages = FALSE;
01256 connection->disconnected_message_arrived = FALSE;
01257 connection->disconnected_message_processed = FALSE;
01258
01259 #ifndef DBUS_DISABLE_CHECKS
01260 connection->generation = _dbus_current_generation;
01261 #endif
01262
01263 _dbus_data_slot_list_init (&connection->slot_list);
01264
01265 connection->client_serial = 1;
01266
01267 connection->disconnect_message_link = disconnect_link;
01268
01269 CONNECTION_LOCK (connection);
01270
01271 if (!_dbus_transport_set_connection (transport, connection))
01272 {
01273 CONNECTION_UNLOCK (connection);
01274
01275 goto error;
01276 }
01277
01278 _dbus_transport_ref (transport);
01279
01280 CONNECTION_UNLOCK (connection);
01281
01282 return connection;
01283
01284 error:
01285 if (disconnect_message != NULL)
01286 dbus_message_unref (disconnect_message);
01287
01288 if (disconnect_link != NULL)
01289 _dbus_list_free_link (disconnect_link);
01290
01291 if (connection != NULL)
01292 {
01293 _dbus_condvar_free_at_location (&connection->io_path_cond);
01294 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01295 _dbus_mutex_free_at_location (&connection->mutex);
01296 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01297 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01298 dbus_free (connection);
01299 }
01300 if (pending_replies)
01301 _dbus_hash_table_unref (pending_replies);
01302
01303 if (watch_list)
01304 _dbus_watch_list_free (watch_list);
01305
01306 if (timeout_list)
01307 _dbus_timeout_list_free (timeout_list);
01308
01309 if (outgoing_counter)
01310 _dbus_counter_unref (outgoing_counter);
01311
01312 if (objects)
01313 _dbus_object_tree_unref (objects);
01314
01315 return NULL;
01316 }
01317
01325 DBusConnection *
01326 _dbus_connection_ref_unlocked (DBusConnection *connection)
01327 {
01328 _dbus_assert (connection != NULL);
01329 _dbus_assert (connection->generation == _dbus_current_generation);
01330
01331 HAVE_LOCK_CHECK (connection);
01332
01333 #ifdef DBUS_HAVE_ATOMIC_INT
01334 _dbus_atomic_inc (&connection->refcount);
01335 #else
01336 _dbus_assert (connection->refcount.value > 0);
01337 connection->refcount.value += 1;
01338 #endif
01339
01340 return connection;
01341 }
01342
01349 void
01350 _dbus_connection_unref_unlocked (DBusConnection *connection)
01351 {
01352 dbus_bool_t last_unref;
01353
01354 HAVE_LOCK_CHECK (connection);
01355
01356 _dbus_assert (connection != NULL);
01357
01358
01359
01360
01361
01362 #ifdef DBUS_HAVE_ATOMIC_INT
01363 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01364 #else
01365 _dbus_assert (connection->refcount.value > 0);
01366
01367 connection->refcount.value -= 1;
01368 last_unref = (connection->refcount.value == 0);
01369 #if 0
01370 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01371 #endif
01372 #endif
01373
01374 if (last_unref)
01375 _dbus_connection_last_unref (connection);
01376 }
01377
01378 static dbus_uint32_t
01379 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01380 {
01381 int serial;
01382
01383 serial = connection->client_serial++;
01384
01385 if (connection->client_serial < 0)
01386 connection->client_serial = 1;
01387
01388 return serial;
01389 }
01390
01404 dbus_bool_t
01405 _dbus_connection_handle_watch (DBusWatch *watch,
01406 unsigned int condition,
01407 void *data)
01408 {
01409 DBusConnection *connection;
01410 dbus_bool_t retval;
01411 DBusDispatchStatus status;
01412
01413 connection = data;
01414
01415 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01416
01417 CONNECTION_LOCK (connection);
01418 _dbus_connection_acquire_io_path (connection, -1);
01419 HAVE_LOCK_CHECK (connection);
01420 retval = _dbus_transport_handle_watch (connection->transport,
01421 watch, condition);
01422
01423 _dbus_connection_release_io_path (connection);
01424
01425 HAVE_LOCK_CHECK (connection);
01426
01427 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01428
01429 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01430
01431
01432 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01433
01434 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01435
01436 return retval;
01437 }
01438
01439 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01440 static DBusHashTable *shared_connections = NULL;
01441
01442 static void
01443 shared_connections_shutdown (void *data)
01444 {
01445 int n_entries;
01446
01447 _DBUS_LOCK (shared_connections);
01448
01449
01450 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01451 {
01452 DBusConnection *connection;
01453 DBusMessage *message;
01454 DBusHashIter iter;
01455
01456 _dbus_hash_iter_init (shared_connections, &iter);
01457 _dbus_hash_iter_next (&iter);
01458
01459 connection = _dbus_hash_iter_get_value (&iter);
01460
01461 _DBUS_UNLOCK (shared_connections);
01462
01463 dbus_connection_ref (connection);
01464 _dbus_connection_close_possibly_shared (connection);
01465
01466
01467 while ((message = dbus_connection_pop_message (connection)))
01468 {
01469 dbus_message_unref (message);
01470 }
01471 dbus_connection_unref (connection);
01472
01473 _DBUS_LOCK (shared_connections);
01474
01475
01476 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01477 }
01478
01479 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01480
01481 _dbus_hash_table_unref (shared_connections);
01482 shared_connections = NULL;
01483
01484 _DBUS_UNLOCK (shared_connections);
01485 }
01486
01487 static dbus_bool_t
01488 connection_lookup_shared (DBusAddressEntry *entry,
01489 DBusConnection **result)
01490 {
01491 _dbus_verbose ("checking for existing connection\n");
01492
01493 *result = NULL;
01494
01495 _DBUS_LOCK (shared_connections);
01496
01497 if (shared_connections == NULL)
01498 {
01499 _dbus_verbose ("creating shared_connections hash table\n");
01500
01501 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01502 dbus_free,
01503 NULL);
01504 if (shared_connections == NULL)
01505 {
01506 _DBUS_UNLOCK (shared_connections);
01507 return FALSE;
01508 }
01509
01510 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01511 {
01512 _dbus_hash_table_unref (shared_connections);
01513 shared_connections = NULL;
01514 _DBUS_UNLOCK (shared_connections);
01515 return FALSE;
01516 }
01517
01518 _dbus_verbose (" successfully created shared_connections\n");
01519
01520 _DBUS_UNLOCK (shared_connections);
01521 return TRUE;
01522 }
01523 else
01524 {
01525 const char *guid;
01526
01527 guid = dbus_address_entry_get_value (entry, "guid");
01528
01529 if (guid != NULL)
01530 {
01531 DBusConnection *connection;
01532
01533 connection = _dbus_hash_table_lookup_string (shared_connections,
01534 guid);
01535
01536 if (connection)
01537 {
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 CONNECTION_LOCK (connection);
01553 if (_dbus_connection_get_is_connected_unlocked (connection))
01554 {
01555 _dbus_connection_ref_unlocked (connection);
01556 *result = connection;
01557 _dbus_verbose ("looked up existing connection to server guid %s\n",
01558 guid);
01559 }
01560 else
01561 {
01562 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01563 guid);
01564 }
01565 CONNECTION_UNLOCK (connection);
01566 }
01567 }
01568
01569 _DBUS_UNLOCK (shared_connections);
01570 return TRUE;
01571 }
01572 }
01573
01574 static dbus_bool_t
01575 connection_record_shared_unlocked (DBusConnection *connection,
01576 const char *guid)
01577 {
01578 char *guid_key;
01579 char *guid_in_connection;
01580
01581 HAVE_LOCK_CHECK (connection);
01582 _dbus_assert (connection->server_guid == NULL);
01583 _dbus_assert (connection->shareable);
01584
01585
01586
01587
01588
01589 _dbus_connection_ref_unlocked (connection);
01590
01591 if (guid == NULL)
01592 return TRUE;
01593
01594
01595
01596
01597
01598
01599 guid_key = _dbus_strdup (guid);
01600 if (guid_key == NULL)
01601 return FALSE;
01602
01603 guid_in_connection = _dbus_strdup (guid);
01604 if (guid_in_connection == NULL)
01605 {
01606 dbus_free (guid_key);
01607 return FALSE;
01608 }
01609
01610 _DBUS_LOCK (shared_connections);
01611 _dbus_assert (shared_connections != NULL);
01612
01613 if (!_dbus_hash_table_insert_string (shared_connections,
01614 guid_key, connection))
01615 {
01616 dbus_free (guid_key);
01617 dbus_free (guid_in_connection);
01618 _DBUS_UNLOCK (shared_connections);
01619 return FALSE;
01620 }
01621
01622 connection->server_guid = guid_in_connection;
01623
01624 _dbus_verbose ("stored connection to %s to be shared\n",
01625 connection->server_guid);
01626
01627 _DBUS_UNLOCK (shared_connections);
01628
01629 _dbus_assert (connection->server_guid != NULL);
01630
01631 return TRUE;
01632 }
01633
01634 static void
01635 connection_forget_shared_unlocked (DBusConnection *connection)
01636 {
01637 HAVE_LOCK_CHECK (connection);
01638
01639 if (!connection->shareable)
01640 return;
01641
01642 if (connection->server_guid != NULL)
01643 {
01644 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01645 connection->server_guid);
01646
01647 _DBUS_LOCK (shared_connections);
01648
01649 if (!_dbus_hash_table_remove_string (shared_connections,
01650 connection->server_guid))
01651 _dbus_assert_not_reached ("connection was not in the shared table");
01652
01653 dbus_free (connection->server_guid);
01654 connection->server_guid = NULL;
01655 _DBUS_UNLOCK (shared_connections);
01656 }
01657
01658
01659 _dbus_connection_unref_unlocked (connection);
01660 }
01661
01662 static DBusConnection*
01663 connection_try_from_address_entry (DBusAddressEntry *entry,
01664 DBusError *error)
01665 {
01666 DBusTransport *transport;
01667 DBusConnection *connection;
01668
01669 transport = _dbus_transport_open (entry, error);
01670
01671 if (transport == NULL)
01672 {
01673 _DBUS_ASSERT_ERROR_IS_SET (error);
01674 return NULL;
01675 }
01676
01677 connection = _dbus_connection_new_for_transport (transport);
01678
01679 _dbus_transport_unref (transport);
01680
01681 if (connection == NULL)
01682 {
01683 _DBUS_SET_OOM (error);
01684 return NULL;
01685 }
01686
01687 #ifndef DBUS_DISABLE_CHECKS
01688 _dbus_assert (!connection->have_connection_lock);
01689 #endif
01690 return connection;
01691 }
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705 static DBusConnection*
01706 _dbus_connection_open_internal (const char *address,
01707 dbus_bool_t shared,
01708 DBusError *error)
01709 {
01710 DBusConnection *connection;
01711 DBusAddressEntry **entries;
01712 DBusError tmp_error;
01713 DBusError first_error;
01714 int len, i;
01715
01716 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01717
01718 _dbus_verbose ("opening %s connection to: %s\n",
01719 shared ? "shared" : "private", address);
01720
01721 if (!dbus_parse_address (address, &entries, &len, error))
01722 return NULL;
01723
01724 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01725
01726 connection = NULL;
01727
01728 dbus_error_init (&tmp_error);
01729 dbus_error_init (&first_error);
01730 for (i = 0; i < len; i++)
01731 {
01732 if (shared)
01733 {
01734 if (!connection_lookup_shared (entries[i], &connection))
01735 _DBUS_SET_OOM (&tmp_error);
01736 }
01737
01738 if (connection == NULL)
01739 {
01740 connection = connection_try_from_address_entry (entries[i],
01741 &tmp_error);
01742
01743 if (connection != NULL && shared)
01744 {
01745 const char *guid;
01746
01747 connection->shareable = TRUE;
01748
01749
01750 guid = dbus_address_entry_get_value (entries[i], "guid");
01751
01752 CONNECTION_LOCK (connection);
01753
01754 if (!connection_record_shared_unlocked (connection, guid))
01755 {
01756 _DBUS_SET_OOM (&tmp_error);
01757 _dbus_connection_close_possibly_shared_and_unlock (connection);
01758 dbus_connection_unref (connection);
01759 connection = NULL;
01760 }
01761 else
01762 CONNECTION_UNLOCK (connection);
01763 }
01764 }
01765
01766 if (connection)
01767 break;
01768
01769 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01770
01771 if (i == 0)
01772 dbus_move_error (&tmp_error, &first_error);
01773 else
01774 dbus_error_free (&tmp_error);
01775 }
01776
01777 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01778 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01779
01780 if (connection == NULL)
01781 {
01782 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01783 dbus_move_error (&first_error, error);
01784 }
01785 else
01786 dbus_error_free (&first_error);
01787
01788 dbus_address_entries_free (entries);
01789 return connection;
01790 }
01791
01800 void
01801 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01802 {
01803 _dbus_assert (connection != NULL);
01804 _dbus_assert (connection->generation == _dbus_current_generation);
01805
01806 CONNECTION_LOCK (connection);
01807 _dbus_connection_close_possibly_shared_and_unlock (connection);
01808 }
01809
01810 static DBusPreallocatedSend*
01811 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01812 {
01813 DBusPreallocatedSend *preallocated;
01814
01815 HAVE_LOCK_CHECK (connection);
01816
01817 _dbus_assert (connection != NULL);
01818
01819 preallocated = dbus_new (DBusPreallocatedSend, 1);
01820 if (preallocated == NULL)
01821 return NULL;
01822
01823 if (connection->link_cache != NULL)
01824 {
01825 preallocated->queue_link =
01826 _dbus_list_pop_first_link (&connection->link_cache);
01827 preallocated->queue_link->data = NULL;
01828 }
01829 else
01830 {
01831 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01832 if (preallocated->queue_link == NULL)
01833 goto failed_0;
01834 }
01835
01836 if (connection->link_cache != NULL)
01837 {
01838 preallocated->counter_link =
01839 _dbus_list_pop_first_link (&connection->link_cache);
01840 preallocated->counter_link->data = connection->outgoing_counter;
01841 }
01842 else
01843 {
01844 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01845 if (preallocated->counter_link == NULL)
01846 goto failed_1;
01847 }
01848
01849 _dbus_counter_ref (preallocated->counter_link->data);
01850
01851 preallocated->connection = connection;
01852
01853 return preallocated;
01854
01855 failed_1:
01856 _dbus_list_free_link (preallocated->queue_link);
01857 failed_0:
01858 dbus_free (preallocated);
01859
01860 return NULL;
01861 }
01862
01863
01864 static void
01865 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01866 DBusPreallocatedSend *preallocated,
01867 DBusMessage *message,
01868 dbus_uint32_t *client_serial)
01869 {
01870 dbus_uint32_t serial;
01871 const char *sig;
01872
01873 preallocated->queue_link->data = message;
01874 _dbus_list_prepend_link (&connection->outgoing_messages,
01875 preallocated->queue_link);
01876
01877 _dbus_message_add_size_counter_link (message,
01878 preallocated->counter_link);
01879
01880 dbus_free (preallocated);
01881 preallocated = NULL;
01882
01883 dbus_message_ref (message);
01884
01885 connection->n_outgoing += 1;
01886
01887 sig = dbus_message_get_signature (message);
01888
01889 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01890 message,
01891 dbus_message_get_type (message),
01892 dbus_message_get_path (message) ?
01893 dbus_message_get_path (message) :
01894 "no path",
01895 dbus_message_get_interface (message) ?
01896 dbus_message_get_interface (message) :
01897 "no interface",
01898 dbus_message_get_member (message) ?
01899 dbus_message_get_member (message) :
01900 "no member",
01901 sig,
01902 dbus_message_get_destination (message) ?
01903 dbus_message_get_destination (message) :
01904 "null",
01905 connection,
01906 connection->n_outgoing);
01907
01908 if (dbus_message_get_serial (message) == 0)
01909 {
01910 serial = _dbus_connection_get_next_client_serial (connection);
01911 _dbus_message_set_serial (message, serial);
01912 if (client_serial)
01913 *client_serial = serial;
01914 }
01915 else
01916 {
01917 if (client_serial)
01918 *client_serial = dbus_message_get_serial (message);
01919 }
01920
01921 _dbus_verbose ("Message %p serial is %u\n",
01922 message, dbus_message_get_serial (message));
01923
01924 _dbus_message_lock (message);
01925
01926
01927
01928
01929 _dbus_connection_do_iteration_unlocked (connection,
01930 DBUS_ITERATION_DO_WRITING,
01931 -1);
01932
01933
01934 if (connection->n_outgoing > 0)
01935 _dbus_connection_wakeup_mainloop (connection);
01936 }
01937
01938 static void
01939 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
01940 DBusPreallocatedSend *preallocated,
01941 DBusMessage *message,
01942 dbus_uint32_t *client_serial)
01943 {
01944 DBusDispatchStatus status;
01945
01946 HAVE_LOCK_CHECK (connection);
01947
01948 _dbus_connection_send_preallocated_unlocked_no_update (connection,
01949 preallocated,
01950 message, client_serial);
01951
01952 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01953 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01954
01955
01956 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01957 }
01958
01968 dbus_bool_t
01969 _dbus_connection_send_and_unlock (DBusConnection *connection,
01970 DBusMessage *message,
01971 dbus_uint32_t *client_serial)
01972 {
01973 DBusPreallocatedSend *preallocated;
01974
01975 _dbus_assert (connection != NULL);
01976 _dbus_assert (message != NULL);
01977
01978 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01979 if (preallocated == NULL)
01980 {
01981 CONNECTION_UNLOCK (connection);
01982 return FALSE;
01983 }
01984
01985 _dbus_connection_send_preallocated_and_unlock (connection,
01986 preallocated,
01987 message,
01988 client_serial);
01989 return TRUE;
01990 }
01991
02016 void
02017 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02018 {
02019 CONNECTION_LOCK (connection);
02020
02021 _dbus_assert (connection->refcount.value > 0);
02022
02023 if (connection->refcount.value == 1)
02024 _dbus_connection_close_possibly_shared_and_unlock (connection);
02025 else
02026 CONNECTION_UNLOCK (connection);
02027 }
02028
02029
02039 static void
02040 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02041 {
02042 if (timeout_milliseconds == -1)
02043 _dbus_sleep_milliseconds (1000);
02044 else if (timeout_milliseconds < 100)
02045 ;
02046 else if (timeout_milliseconds <= 1000)
02047 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02048 else
02049 _dbus_sleep_milliseconds (1000);
02050 }
02051
02052 static DBusMessage *
02053 generate_local_error_message (dbus_uint32_t serial,
02054 char *error_name,
02055 char *error_msg)
02056 {
02057 DBusMessage *message;
02058 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02059 if (!message)
02060 goto out;
02061
02062 if (!dbus_message_set_error_name (message, error_name))
02063 {
02064 dbus_message_unref (message);
02065 message = NULL;
02066 goto out;
02067 }
02068
02069 dbus_message_set_no_reply (message, TRUE);
02070
02071 if (!dbus_message_set_reply_serial (message,
02072 serial))
02073 {
02074 dbus_message_unref (message);
02075 message = NULL;
02076 goto out;
02077 }
02078
02079 if (error_msg != NULL)
02080 {
02081 DBusMessageIter iter;
02082
02083 dbus_message_iter_init_append (message, &iter);
02084 if (!dbus_message_iter_append_basic (&iter,
02085 DBUS_TYPE_STRING,
02086 &error_msg))
02087 {
02088 dbus_message_unref (message);
02089 message = NULL;
02090 goto out;
02091 }
02092 }
02093
02094 out:
02095 return message;
02096 }
02097
02098
02099
02100
02101
02102 static DBusMessage*
02103 check_for_reply_unlocked (DBusConnection *connection,
02104 dbus_uint32_t client_serial)
02105 {
02106 DBusList *link;
02107
02108 HAVE_LOCK_CHECK (connection);
02109
02110 link = _dbus_list_get_first_link (&connection->incoming_messages);
02111
02112 while (link != NULL)
02113 {
02114 DBusMessage *reply = link->data;
02115
02116 if (dbus_message_get_reply_serial (reply) == client_serial)
02117 {
02118 _dbus_list_remove_link (&connection->incoming_messages, link);
02119 connection->n_incoming -= 1;
02120 return reply;
02121 }
02122 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02123 }
02124
02125 return NULL;
02126 }
02127
02128 static void
02129 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02130 {
02131
02132
02133
02134
02135
02136 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02137 {
02138 DBusPendingCall *pending;
02139 DBusHashIter iter;
02140
02141 _dbus_hash_iter_init (connection->pending_replies, &iter);
02142 _dbus_hash_iter_next (&iter);
02143
02144 pending = _dbus_hash_iter_get_value (&iter);
02145 _dbus_pending_call_ref_unlocked (pending);
02146
02147 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02148 connection);
02149 _dbus_connection_remove_timeout_unlocked (connection,
02150 _dbus_pending_call_get_timeout_unlocked (pending));
02151 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02152 _dbus_hash_iter_remove_entry (&iter);
02153
02154 _dbus_pending_call_unref_and_unlock (pending);
02155 CONNECTION_LOCK (connection);
02156 }
02157 HAVE_LOCK_CHECK (connection);
02158 }
02159
02160 static void
02161 complete_pending_call_and_unlock (DBusConnection *connection,
02162 DBusPendingCall *pending,
02163 DBusMessage *message)
02164 {
02165 _dbus_pending_call_set_reply_unlocked (pending, message);
02166 _dbus_pending_call_ref_unlocked (pending);
02167 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02168
02169
02170 _dbus_pending_call_complete (pending);
02171 dbus_pending_call_unref (pending);
02172 }
02173
02174 static dbus_bool_t
02175 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02176 DBusPendingCall *pending)
02177 {
02178 DBusMessage *reply;
02179 DBusDispatchStatus status;
02180
02181 reply = check_for_reply_unlocked (connection,
02182 _dbus_pending_call_get_reply_serial_unlocked (pending));
02183 if (reply != NULL)
02184 {
02185 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02186
02187 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02188
02189 complete_pending_call_and_unlock (connection, pending, reply);
02190 dbus_message_unref (reply);
02191
02192 CONNECTION_LOCK (connection);
02193 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02194 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02195 dbus_pending_call_unref (pending);
02196
02197 return TRUE;
02198 }
02199
02200 return FALSE;
02201 }
02202
02217 void
02218 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02219 {
02220 long start_tv_sec, start_tv_usec;
02221 long end_tv_sec, end_tv_usec;
02222 long tv_sec, tv_usec;
02223 DBusDispatchStatus status;
02224 DBusConnection *connection;
02225 dbus_uint32_t client_serial;
02226 int timeout_milliseconds;
02227
02228 _dbus_assert (pending != NULL);
02229
02230 if (dbus_pending_call_get_completed (pending))
02231 return;
02232
02233 dbus_pending_call_ref (pending);
02234
02235 connection = _dbus_pending_call_get_connection_and_lock (pending);
02236
02237
02238 _dbus_connection_flush_unlocked (connection);
02239
02240 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02241
02242
02243
02244
02245
02246 timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02247
02248 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02249 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02250 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02251 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02252 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02253
02254 _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",
02255 timeout_milliseconds,
02256 client_serial,
02257 start_tv_sec, start_tv_usec,
02258 end_tv_sec, end_tv_usec);
02259
02260
02261
02262 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02263 return;
02264
02265
02266
02267 _dbus_connection_do_iteration_unlocked (connection,
02268 DBUS_ITERATION_DO_READING |
02269 DBUS_ITERATION_BLOCK,
02270 timeout_milliseconds);
02271
02272 recheck_status:
02273
02274 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02275
02276 HAVE_LOCK_CHECK (connection);
02277
02278
02279
02280 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02281
02282
02283
02284
02285 if (_dbus_pending_call_get_completed_unlocked (pending))
02286 {
02287 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02288 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02289 dbus_pending_call_unref (pending);
02290 return;
02291 }
02292
02293 if (status == DBUS_DISPATCH_DATA_REMAINS) {
02294 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02295 return;
02296 }
02297
02298 _dbus_get_current_time (&tv_sec, &tv_usec);
02299
02300 if (!_dbus_connection_get_is_connected_unlocked (connection))
02301 {
02302 DBusMessage *error_msg;
02303
02304 error_msg = generate_local_error_message (client_serial,
02305 DBUS_ERROR_DISCONNECTED,
02306 "Connection was disconnected before a reply was received");
02307
02308
02309 complete_pending_call_and_unlock (connection, pending, error_msg);
02310 dbus_pending_call_unref (pending);
02311 return;
02312 }
02313 else if (tv_sec < start_tv_sec)
02314 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02315 else if (connection->disconnect_message_link == NULL)
02316 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02317 else if (tv_sec < end_tv_sec ||
02318 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02319 {
02320 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02321 (end_tv_usec - tv_usec) / 1000;
02322 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02323 _dbus_assert (timeout_milliseconds >= 0);
02324
02325 if (status == DBUS_DISPATCH_NEED_MEMORY)
02326 {
02327
02328
02329
02330
02331 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02332
02333 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02334 }
02335 else
02336 {
02337
02338 _dbus_connection_do_iteration_unlocked (connection,
02339 DBUS_ITERATION_DO_READING |
02340 DBUS_ITERATION_BLOCK,
02341 timeout_milliseconds);
02342 }
02343
02344 goto recheck_status;
02345 }
02346
02347 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02348 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02349
02350 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02351
02352
02353 complete_pending_call_and_unlock (connection, pending, NULL);
02354
02355
02356 CONNECTION_LOCK (connection);
02357 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02358 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02359 dbus_pending_call_unref (pending);
02360 }
02361
02398 DBusConnection*
02399 dbus_connection_open (const char *address,
02400 DBusError *error)
02401 {
02402 DBusConnection *connection;
02403
02404 _dbus_return_val_if_fail (address != NULL, NULL);
02405 _dbus_return_val_if_error_is_set (error, NULL);
02406
02407 connection = _dbus_connection_open_internal (address,
02408 TRUE,
02409 error);
02410
02411 return connection;
02412 }
02413
02441 DBusConnection*
02442 dbus_connection_open_private (const char *address,
02443 DBusError *error)
02444 {
02445 DBusConnection *connection;
02446
02447 _dbus_return_val_if_fail (address != NULL, NULL);
02448 _dbus_return_val_if_error_is_set (error, NULL);
02449
02450 connection = _dbus_connection_open_internal (address,
02451 FALSE,
02452 error);
02453
02454 return connection;
02455 }
02456
02463 DBusConnection *
02464 dbus_connection_ref (DBusConnection *connection)
02465 {
02466 _dbus_return_val_if_fail (connection != NULL, NULL);
02467 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02468
02469
02470
02471
02472
02473 #ifdef DBUS_HAVE_ATOMIC_INT
02474 _dbus_atomic_inc (&connection->refcount);
02475 #else
02476 CONNECTION_LOCK (connection);
02477 _dbus_assert (connection->refcount.value > 0);
02478
02479 connection->refcount.value += 1;
02480 CONNECTION_UNLOCK (connection);
02481 #endif
02482
02483 return connection;
02484 }
02485
02486 static void
02487 free_outgoing_message (void *element,
02488 void *data)
02489 {
02490 DBusMessage *message = element;
02491 DBusConnection *connection = data;
02492
02493 _dbus_message_remove_size_counter (message,
02494 connection->outgoing_counter,
02495 NULL);
02496 dbus_message_unref (message);
02497 }
02498
02499
02500
02501
02502
02503 static void
02504 _dbus_connection_last_unref (DBusConnection *connection)
02505 {
02506 DBusList *link;
02507
02508 _dbus_verbose ("Finalizing connection %p\n", connection);
02509
02510 _dbus_assert (connection->refcount.value == 0);
02511
02512
02513
02514
02515 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02516 _dbus_assert (connection->server_guid == NULL);
02517
02518
02519 _dbus_object_tree_free_all_unlocked (connection->objects);
02520
02521 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02522 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02523 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02524
02525 _dbus_watch_list_free (connection->watches);
02526 connection->watches = NULL;
02527
02528 _dbus_timeout_list_free (connection->timeouts);
02529 connection->timeouts = NULL;
02530
02531 _dbus_data_slot_list_free (&connection->slot_list);
02532
02533 link = _dbus_list_get_first_link (&connection->filter_list);
02534 while (link != NULL)
02535 {
02536 DBusMessageFilter *filter = link->data;
02537 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02538
02539 filter->function = NULL;
02540 _dbus_message_filter_unref (filter);
02541 link->data = NULL;
02542
02543 link = next;
02544 }
02545 _dbus_list_clear (&connection->filter_list);
02546
02547
02548
02549 _dbus_object_tree_unref (connection->objects);
02550
02551 _dbus_hash_table_unref (connection->pending_replies);
02552 connection->pending_replies = NULL;
02553
02554 _dbus_list_clear (&connection->filter_list);
02555
02556 _dbus_list_foreach (&connection->outgoing_messages,
02557 free_outgoing_message,
02558 connection);
02559 _dbus_list_clear (&connection->outgoing_messages);
02560
02561 _dbus_list_foreach (&connection->incoming_messages,
02562 (DBusForeachFunction) dbus_message_unref,
02563 NULL);
02564 _dbus_list_clear (&connection->incoming_messages);
02565
02566 _dbus_counter_unref (connection->outgoing_counter);
02567
02568 _dbus_transport_unref (connection->transport);
02569
02570 if (connection->disconnect_message_link)
02571 {
02572 DBusMessage *message = connection->disconnect_message_link->data;
02573 dbus_message_unref (message);
02574 _dbus_list_free_link (connection->disconnect_message_link);
02575 }
02576
02577 _dbus_list_clear (&connection->link_cache);
02578
02579 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02580 _dbus_condvar_free_at_location (&connection->io_path_cond);
02581
02582 _dbus_mutex_free_at_location (&connection->io_path_mutex);
02583 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02584
02585 _dbus_mutex_free_at_location (&connection->mutex);
02586
02587 dbus_free (connection);
02588 }
02589
02609 void
02610 dbus_connection_unref (DBusConnection *connection)
02611 {
02612 dbus_bool_t last_unref;
02613
02614 _dbus_return_if_fail (connection != NULL);
02615 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02616
02617
02618
02619
02620
02621 #ifdef DBUS_HAVE_ATOMIC_INT
02622 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02623 #else
02624 CONNECTION_LOCK (connection);
02625
02626 _dbus_assert (connection->refcount.value > 0);
02627
02628 connection->refcount.value -= 1;
02629 last_unref = (connection->refcount.value == 0);
02630
02631 #if 0
02632 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02633 #endif
02634
02635 CONNECTION_UNLOCK (connection);
02636 #endif
02637
02638 if (last_unref)
02639 {
02640 #ifndef DBUS_DISABLE_CHECKS
02641 if (_dbus_transport_get_is_connected (connection->transport))
02642 {
02643 _dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
02644 connection->shareable ?
02645 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02646 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02647 return;
02648 }
02649 #endif
02650 _dbus_connection_last_unref (connection);
02651 }
02652 }
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663 static void
02664 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02665 {
02666 DBusDispatchStatus status;
02667
02668 HAVE_LOCK_CHECK (connection);
02669
02670 _dbus_verbose ("Disconnecting %p\n", connection);
02671
02672
02673
02674
02675
02676 _dbus_connection_ref_unlocked (connection);
02677
02678 _dbus_transport_disconnect (connection->transport);
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02690
02691
02692 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02693
02694
02695 dbus_connection_unref (connection);
02696 }
02697
02740 void
02741 dbus_connection_close (DBusConnection *connection)
02742 {
02743 _dbus_return_if_fail (connection != NULL);
02744 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02745
02746 CONNECTION_LOCK (connection);
02747
02748 #ifndef DBUS_DISABLE_CHECKS
02749 if (connection->shareable)
02750 {
02751 CONNECTION_UNLOCK (connection);
02752
02753 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02754 return;
02755 }
02756 #endif
02757
02758 _dbus_connection_close_possibly_shared_and_unlock (connection);
02759 }
02760
02761 static dbus_bool_t
02762 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02763 {
02764 HAVE_LOCK_CHECK (connection);
02765 return _dbus_transport_get_is_connected (connection->transport);
02766 }
02767
02781 dbus_bool_t
02782 dbus_connection_get_is_connected (DBusConnection *connection)
02783 {
02784 dbus_bool_t res;
02785
02786 _dbus_return_val_if_fail (connection != NULL, FALSE);
02787
02788 CONNECTION_LOCK (connection);
02789 res = _dbus_connection_get_is_connected_unlocked (connection);
02790 CONNECTION_UNLOCK (connection);
02791
02792 return res;
02793 }
02794
02803 dbus_bool_t
02804 dbus_connection_get_is_authenticated (DBusConnection *connection)
02805 {
02806 dbus_bool_t res;
02807
02808 _dbus_return_val_if_fail (connection != NULL, FALSE);
02809
02810 CONNECTION_LOCK (connection);
02811 res = _dbus_transport_get_is_authenticated (connection->transport);
02812 CONNECTION_UNLOCK (connection);
02813
02814 return res;
02815 }
02816
02837 dbus_bool_t
02838 dbus_connection_get_is_anonymous (DBusConnection *connection)
02839 {
02840 dbus_bool_t res;
02841
02842 _dbus_return_val_if_fail (connection != NULL, FALSE);
02843
02844 CONNECTION_LOCK (connection);
02845 res = _dbus_transport_get_is_anonymous (connection->transport);
02846 CONNECTION_UNLOCK (connection);
02847
02848 return res;
02849 }
02850
02882 char*
02883 dbus_connection_get_server_id (DBusConnection *connection)
02884 {
02885 char *id;
02886
02887 _dbus_return_val_if_fail (connection != NULL, FALSE);
02888
02889 CONNECTION_LOCK (connection);
02890 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02891 CONNECTION_UNLOCK (connection);
02892
02893 return id;
02894 }
02895
02909 void
02910 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02911 dbus_bool_t exit_on_disconnect)
02912 {
02913 _dbus_return_if_fail (connection != NULL);
02914
02915 CONNECTION_LOCK (connection);
02916 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02917 CONNECTION_UNLOCK (connection);
02918 }
02919
02929 DBusPreallocatedSend*
02930 dbus_connection_preallocate_send (DBusConnection *connection)
02931 {
02932 DBusPreallocatedSend *preallocated;
02933
02934 _dbus_return_val_if_fail (connection != NULL, NULL);
02935
02936 CONNECTION_LOCK (connection);
02937
02938 preallocated =
02939 _dbus_connection_preallocate_send_unlocked (connection);
02940
02941 CONNECTION_UNLOCK (connection);
02942
02943 return preallocated;
02944 }
02945
02955 void
02956 dbus_connection_free_preallocated_send (DBusConnection *connection,
02957 DBusPreallocatedSend *preallocated)
02958 {
02959 _dbus_return_if_fail (connection != NULL);
02960 _dbus_return_if_fail (preallocated != NULL);
02961 _dbus_return_if_fail (connection == preallocated->connection);
02962
02963 _dbus_list_free_link (preallocated->queue_link);
02964 _dbus_counter_unref (preallocated->counter_link->data);
02965 _dbus_list_free_link (preallocated->counter_link);
02966 dbus_free (preallocated);
02967 }
02968
02981 void
02982 dbus_connection_send_preallocated (DBusConnection *connection,
02983 DBusPreallocatedSend *preallocated,
02984 DBusMessage *message,
02985 dbus_uint32_t *client_serial)
02986 {
02987 _dbus_return_if_fail (connection != NULL);
02988 _dbus_return_if_fail (preallocated != NULL);
02989 _dbus_return_if_fail (message != NULL);
02990 _dbus_return_if_fail (preallocated->connection == connection);
02991 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02992 dbus_message_get_member (message) != NULL);
02993 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02994 (dbus_message_get_interface (message) != NULL &&
02995 dbus_message_get_member (message) != NULL));
02996
02997 CONNECTION_LOCK (connection);
02998 _dbus_connection_send_preallocated_and_unlock (connection,
02999 preallocated,
03000 message, client_serial);
03001 }
03002
03003 static dbus_bool_t
03004 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03005 DBusMessage *message,
03006 dbus_uint32_t *client_serial)
03007 {
03008 DBusPreallocatedSend *preallocated;
03009
03010 _dbus_assert (connection != NULL);
03011 _dbus_assert (message != NULL);
03012
03013 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03014 if (preallocated == NULL)
03015 return FALSE;
03016
03017 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03018 preallocated,
03019 message,
03020 client_serial);
03021 return TRUE;
03022 }
03023
03045 dbus_bool_t
03046 dbus_connection_send (DBusConnection *connection,
03047 DBusMessage *message,
03048 dbus_uint32_t *serial)
03049 {
03050 _dbus_return_val_if_fail (connection != NULL, FALSE);
03051 _dbus_return_val_if_fail (message != NULL, FALSE);
03052
03053 CONNECTION_LOCK (connection);
03054
03055 return _dbus_connection_send_and_unlock (connection,
03056 message,
03057 serial);
03058 }
03059
03060 static dbus_bool_t
03061 reply_handler_timeout (void *data)
03062 {
03063 DBusConnection *connection;
03064 DBusDispatchStatus status;
03065 DBusPendingCall *pending = data;
03066
03067 connection = _dbus_pending_call_get_connection_and_lock (pending);
03068
03069 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03070 connection);
03071 _dbus_connection_remove_timeout_unlocked (connection,
03072 _dbus_pending_call_get_timeout_unlocked (pending));
03073 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03074
03075 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03076 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03077
03078
03079 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03080
03081 return TRUE;
03082 }
03083
03121 dbus_bool_t
03122 dbus_connection_send_with_reply (DBusConnection *connection,
03123 DBusMessage *message,
03124 DBusPendingCall **pending_return,
03125 int timeout_milliseconds)
03126 {
03127 DBusPendingCall *pending;
03128 dbus_int32_t serial = -1;
03129 DBusDispatchStatus status;
03130
03131 _dbus_return_val_if_fail (connection != NULL, FALSE);
03132 _dbus_return_val_if_fail (message != NULL, FALSE);
03133 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03134
03135 if (pending_return)
03136 *pending_return = NULL;
03137
03138 CONNECTION_LOCK (connection);
03139
03140 if (!_dbus_connection_get_is_connected_unlocked (connection))
03141 {
03142 CONNECTION_UNLOCK (connection);
03143
03144 *pending_return = NULL;
03145
03146 return TRUE;
03147 }
03148
03149 pending = _dbus_pending_call_new_unlocked (connection,
03150 timeout_milliseconds,
03151 reply_handler_timeout);
03152
03153 if (pending == NULL)
03154 {
03155 CONNECTION_UNLOCK (connection);
03156 return FALSE;
03157 }
03158
03159
03160 serial = dbus_message_get_serial (message);
03161 if (serial == 0)
03162 {
03163 serial = _dbus_connection_get_next_client_serial (connection);
03164 _dbus_message_set_serial (message, serial);
03165 }
03166
03167 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03168 goto error;
03169
03170
03171
03172
03173
03174 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03175 pending))
03176 goto error;
03177
03178 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03179 {
03180 _dbus_connection_detach_pending_call_and_unlock (connection,
03181 pending);
03182 goto error_unlocked;
03183 }
03184
03185 if (pending_return)
03186 *pending_return = pending;
03187 else
03188 {
03189 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03190
03191
03192
03193 }
03194
03195 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03196
03197
03198 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03199
03200 if (pending_return == NULL)
03201 dbus_pending_call_unref (pending);
03202
03203 return TRUE;
03204
03205 error:
03206 CONNECTION_UNLOCK (connection);
03207 error_unlocked:
03208 dbus_pending_call_unref (pending);
03209 return FALSE;
03210 }
03211
03242 DBusMessage*
03243 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03244 DBusMessage *message,
03245 int timeout_milliseconds,
03246 DBusError *error)
03247 {
03248 DBusMessage *reply;
03249 DBusPendingCall *pending;
03250
03251 _dbus_return_val_if_fail (connection != NULL, NULL);
03252 _dbus_return_val_if_fail (message != NULL, NULL);
03253 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03254 _dbus_return_val_if_error_is_set (error, NULL);
03255
03256 if (!dbus_connection_send_with_reply (connection, message,
03257 &pending, timeout_milliseconds))
03258 {
03259 _DBUS_SET_OOM (error);
03260 return NULL;
03261 }
03262
03263 if (pending == NULL)
03264 {
03265 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03266 return NULL;
03267 }
03268
03269 dbus_pending_call_block (pending);
03270
03271 reply = dbus_pending_call_steal_reply (pending);
03272 dbus_pending_call_unref (pending);
03273
03274
03275
03276
03277 _dbus_assert (reply != NULL);
03278
03279 if (dbus_set_error_from_message (error, reply))
03280 {
03281 dbus_message_unref (reply);
03282 return NULL;
03283 }
03284 else
03285 return reply;
03286 }
03287
03296 DBusDispatchStatus
03297 _dbus_connection_flush_unlocked (DBusConnection *connection)
03298 {
03299
03300
03301
03302
03303
03304 DBusDispatchStatus status;
03305
03306 HAVE_LOCK_CHECK (connection);
03307
03308 while (connection->n_outgoing > 0 &&
03309 _dbus_connection_get_is_connected_unlocked (connection))
03310 {
03311 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03312 HAVE_LOCK_CHECK (connection);
03313 _dbus_connection_do_iteration_unlocked (connection,
03314 DBUS_ITERATION_DO_READING |
03315 DBUS_ITERATION_DO_WRITING |
03316 DBUS_ITERATION_BLOCK,
03317 -1);
03318 }
03319
03320 HAVE_LOCK_CHECK (connection);
03321 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03322 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03323
03324 HAVE_LOCK_CHECK (connection);
03325 return status;
03326 }
03327
03333 void
03334 dbus_connection_flush (DBusConnection *connection)
03335 {
03336
03337
03338
03339
03340
03341 DBusDispatchStatus status;
03342
03343 _dbus_return_if_fail (connection != NULL);
03344
03345 CONNECTION_LOCK (connection);
03346
03347 status = _dbus_connection_flush_unlocked (connection);
03348
03349 HAVE_LOCK_CHECK (connection);
03350
03351 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03352
03353 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03354 }
03355
03366 static dbus_bool_t
03367 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03368 int timeout_milliseconds,
03369 dbus_bool_t dispatch)
03370 {
03371 DBusDispatchStatus dstatus;
03372 dbus_bool_t no_progress_possible;
03373
03374 dstatus = dbus_connection_get_dispatch_status (connection);
03375
03376 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03377 {
03378 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03379 dbus_connection_dispatch (connection);
03380 CONNECTION_LOCK (connection);
03381 }
03382 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03383 {
03384 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03385 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03386 CONNECTION_LOCK (connection);
03387 }
03388 else
03389 {
03390 CONNECTION_LOCK (connection);
03391 if (_dbus_connection_get_is_connected_unlocked (connection))
03392 {
03393 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03394 _dbus_connection_do_iteration_unlocked (connection,
03395 DBUS_ITERATION_DO_READING |
03396 DBUS_ITERATION_DO_WRITING |
03397 DBUS_ITERATION_BLOCK,
03398 timeout_milliseconds);
03399 }
03400 }
03401
03402 HAVE_LOCK_CHECK (connection);
03403
03404
03405
03406
03407 if (dispatch)
03408 no_progress_possible = connection->n_incoming == 0 &&
03409 connection->disconnect_message_link == NULL;
03410 else
03411 no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03412 CONNECTION_UNLOCK (connection);
03413 return !no_progress_possible;
03414 }
03415
03416
03451 dbus_bool_t
03452 dbus_connection_read_write_dispatch (DBusConnection *connection,
03453 int timeout_milliseconds)
03454 {
03455 _dbus_return_val_if_fail (connection != NULL, FALSE);
03456 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03457 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03458 }
03459
03483 dbus_bool_t
03484 dbus_connection_read_write (DBusConnection *connection,
03485 int timeout_milliseconds)
03486 {
03487 _dbus_return_val_if_fail (connection != NULL, FALSE);
03488 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03489 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03490 }
03491
03492
03493
03494
03495
03496
03497 static void
03498 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03499 DBusMessage *head_of_queue)
03500 {
03501 HAVE_LOCK_CHECK (connection);
03502
03503
03504 if (connection->disconnect_message_link == NULL &&
03505 dbus_message_is_signal (head_of_queue,
03506 DBUS_INTERFACE_LOCAL,
03507 "Disconnected"))
03508 {
03509 connection->disconnected_message_arrived = TRUE;
03510 }
03511 }
03512
03532 DBusMessage*
03533 dbus_connection_borrow_message (DBusConnection *connection)
03534 {
03535 DBusDispatchStatus status;
03536 DBusMessage *message;
03537
03538 _dbus_return_val_if_fail (connection != NULL, NULL);
03539
03540 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03541
03542
03543
03544
03545 status = dbus_connection_get_dispatch_status (connection);
03546 if (status != DBUS_DISPATCH_DATA_REMAINS)
03547 return NULL;
03548
03549 CONNECTION_LOCK (connection);
03550
03551 _dbus_connection_acquire_dispatch (connection);
03552
03553
03554 _dbus_assert (connection->message_borrowed == NULL);
03555
03556 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03557
03558 message = connection->message_borrowed;
03559
03560 check_disconnected_message_arrived_unlocked (connection, message);
03561
03562
03563 if (message == NULL)
03564 _dbus_connection_release_dispatch (connection);
03565
03566 CONNECTION_UNLOCK (connection);
03567
03568
03569
03570 return message;
03571 }
03572
03581 void
03582 dbus_connection_return_message (DBusConnection *connection,
03583 DBusMessage *message)
03584 {
03585 DBusDispatchStatus status;
03586
03587 _dbus_return_if_fail (connection != NULL);
03588 _dbus_return_if_fail (message != NULL);
03589 _dbus_return_if_fail (message == connection->message_borrowed);
03590 _dbus_return_if_fail (connection->dispatch_acquired);
03591
03592 CONNECTION_LOCK (connection);
03593
03594 _dbus_assert (message == connection->message_borrowed);
03595
03596 connection->message_borrowed = NULL;
03597
03598 _dbus_connection_release_dispatch (connection);
03599
03600 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03601 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03602 }
03603
03613 void
03614 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03615 DBusMessage *message)
03616 {
03617 DBusMessage *pop_message;
03618 DBusDispatchStatus status;
03619
03620 _dbus_return_if_fail (connection != NULL);
03621 _dbus_return_if_fail (message != NULL);
03622 _dbus_return_if_fail (message == connection->message_borrowed);
03623 _dbus_return_if_fail (connection->dispatch_acquired);
03624
03625 CONNECTION_LOCK (connection);
03626
03627 _dbus_assert (message == connection->message_borrowed);
03628
03629 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03630 _dbus_assert (message == pop_message);
03631
03632 connection->n_incoming -= 1;
03633
03634 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03635 message, connection->n_incoming);
03636
03637 connection->message_borrowed = NULL;
03638
03639 _dbus_connection_release_dispatch (connection);
03640
03641 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03642 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03643 }
03644
03645
03646
03647
03648 static DBusList*
03649 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03650 {
03651 HAVE_LOCK_CHECK (connection);
03652
03653 _dbus_assert (connection->message_borrowed == NULL);
03654
03655 if (connection->n_incoming > 0)
03656 {
03657 DBusList *link;
03658
03659 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03660 connection->n_incoming -= 1;
03661
03662 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03663 link->data,
03664 dbus_message_get_type (link->data),
03665 dbus_message_get_path (link->data) ?
03666 dbus_message_get_path (link->data) :
03667 "no path",
03668 dbus_message_get_interface (link->data) ?
03669 dbus_message_get_interface (link->data) :
03670 "no interface",
03671 dbus_message_get_member (link->data) ?
03672 dbus_message_get_member (link->data) :
03673 "no member",
03674 dbus_message_get_signature (link->data),
03675 connection, connection->n_incoming);
03676
03677 check_disconnected_message_arrived_unlocked (connection, link->data);
03678
03679 return link;
03680 }
03681 else
03682 return NULL;
03683 }
03684
03685
03686
03687
03688 static DBusMessage*
03689 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03690 {
03691 DBusList *link;
03692
03693 HAVE_LOCK_CHECK (connection);
03694
03695 link = _dbus_connection_pop_message_link_unlocked (connection);
03696
03697 if (link != NULL)
03698 {
03699 DBusMessage *message;
03700
03701 message = link->data;
03702
03703 _dbus_list_free_link (link);
03704
03705 return message;
03706 }
03707 else
03708 return NULL;
03709 }
03710
03711 static void
03712 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03713 DBusList *message_link)
03714 {
03715 HAVE_LOCK_CHECK (connection);
03716
03717 _dbus_assert (message_link != NULL);
03718
03719 _dbus_assert (connection->message_borrowed == NULL);
03720
03721 _dbus_assert (connection->dispatch_acquired);
03722
03723 _dbus_list_prepend_link (&connection->incoming_messages,
03724 message_link);
03725 connection->n_incoming += 1;
03726
03727 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03728 message_link->data,
03729 dbus_message_get_type (message_link->data),
03730 dbus_message_get_interface (message_link->data) ?
03731 dbus_message_get_interface (message_link->data) :
03732 "no interface",
03733 dbus_message_get_member (message_link->data) ?
03734 dbus_message_get_member (message_link->data) :
03735 "no member",
03736 dbus_message_get_signature (message_link->data),
03737 connection, connection->n_incoming);
03738 }
03739
03759 DBusMessage*
03760 dbus_connection_pop_message (DBusConnection *connection)
03761 {
03762 DBusMessage *message;
03763 DBusDispatchStatus status;
03764
03765 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03766
03767
03768
03769
03770 status = dbus_connection_get_dispatch_status (connection);
03771 if (status != DBUS_DISPATCH_DATA_REMAINS)
03772 return NULL;
03773
03774 CONNECTION_LOCK (connection);
03775 _dbus_connection_acquire_dispatch (connection);
03776 HAVE_LOCK_CHECK (connection);
03777
03778 message = _dbus_connection_pop_message_unlocked (connection);
03779
03780 _dbus_verbose ("Returning popped message %p\n", message);
03781
03782 _dbus_connection_release_dispatch (connection);
03783
03784 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03785 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03786
03787 return message;
03788 }
03789
03797 static void
03798 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03799 {
03800 HAVE_LOCK_CHECK (connection);
03801
03802 _dbus_connection_ref_unlocked (connection);
03803 CONNECTION_UNLOCK (connection);
03804
03805 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03806 _dbus_mutex_lock (connection->dispatch_mutex);
03807
03808 while (connection->dispatch_acquired)
03809 {
03810 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03811 _dbus_condvar_wait (connection->dispatch_cond,
03812 connection->dispatch_mutex);
03813 }
03814
03815 _dbus_assert (!connection->dispatch_acquired);
03816
03817 connection->dispatch_acquired = TRUE;
03818
03819 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03820 _dbus_mutex_unlock (connection->dispatch_mutex);
03821
03822 CONNECTION_LOCK (connection);
03823 _dbus_connection_unref_unlocked (connection);
03824 }
03825
03833 static void
03834 _dbus_connection_release_dispatch (DBusConnection *connection)
03835 {
03836 HAVE_LOCK_CHECK (connection);
03837
03838 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03839 _dbus_mutex_lock (connection->dispatch_mutex);
03840
03841 _dbus_assert (connection->dispatch_acquired);
03842
03843 connection->dispatch_acquired = FALSE;
03844 _dbus_condvar_wake_one (connection->dispatch_cond);
03845
03846 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03847 _dbus_mutex_unlock (connection->dispatch_mutex);
03848 }
03849
03850 static void
03851 _dbus_connection_failed_pop (DBusConnection *connection,
03852 DBusList *message_link)
03853 {
03854 _dbus_list_prepend_link (&connection->incoming_messages,
03855 message_link);
03856 connection->n_incoming += 1;
03857 }
03858
03859
03860 static void
03861 notify_disconnected_unlocked (DBusConnection *connection)
03862 {
03863 HAVE_LOCK_CHECK (connection);
03864
03865
03866
03867
03868
03869
03870
03871 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03872
03873
03874
03875
03876
03877 if (connection->n_outgoing > 0)
03878 {
03879 DBusList *link;
03880
03881 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03882 connection->n_outgoing);
03883
03884 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03885 {
03886 _dbus_connection_message_sent (connection, link->data);
03887 }
03888 }
03889 }
03890
03891
03892 static DBusDispatchStatus
03893 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03894 {
03895 HAVE_LOCK_CHECK (connection);
03896
03897 if (connection->disconnect_message_link != NULL)
03898 {
03899 _dbus_verbose ("Sending disconnect message from %s\n",
03900 _DBUS_FUNCTION_NAME);
03901
03902
03903
03904
03905 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03906
03907
03908
03909
03910 _dbus_connection_queue_synthesized_message_link (connection,
03911 connection->disconnect_message_link);
03912 connection->disconnect_message_link = NULL;
03913
03914 return DBUS_DISPATCH_DATA_REMAINS;
03915 }
03916
03917 return DBUS_DISPATCH_COMPLETE;
03918 }
03919
03920 static DBusDispatchStatus
03921 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03922 {
03923 HAVE_LOCK_CHECK (connection);
03924
03925 if (connection->n_incoming > 0)
03926 return DBUS_DISPATCH_DATA_REMAINS;
03927 else if (!_dbus_transport_queue_messages (connection->transport))
03928 return DBUS_DISPATCH_NEED_MEMORY;
03929 else
03930 {
03931 DBusDispatchStatus status;
03932 dbus_bool_t is_connected;
03933
03934 status = _dbus_transport_get_dispatch_status (connection->transport);
03935 is_connected = _dbus_transport_get_is_connected (connection->transport);
03936
03937 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03938 DISPATCH_STATUS_NAME (status), is_connected);
03939
03940 if (!is_connected)
03941 {
03942
03943
03944
03945
03946
03947
03948 notify_disconnected_unlocked (connection);
03949
03950
03951
03952
03953
03954
03955 if (status == DBUS_DISPATCH_COMPLETE)
03956 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03957 }
03958
03959 if (status != DBUS_DISPATCH_COMPLETE)
03960 return status;
03961 else if (connection->n_incoming > 0)
03962 return DBUS_DISPATCH_DATA_REMAINS;
03963 else
03964 return DBUS_DISPATCH_COMPLETE;
03965 }
03966 }
03967
03968 static void
03969 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03970 DBusDispatchStatus new_status)
03971 {
03972 dbus_bool_t changed;
03973 DBusDispatchStatusFunction function;
03974 void *data;
03975
03976 HAVE_LOCK_CHECK (connection);
03977
03978 _dbus_connection_ref_unlocked (connection);
03979
03980 changed = new_status != connection->last_dispatch_status;
03981
03982 connection->last_dispatch_status = new_status;
03983
03984 function = connection->dispatch_status_function;
03985 data = connection->dispatch_status_data;
03986
03987 if (connection->disconnected_message_arrived &&
03988 !connection->disconnected_message_processed)
03989 {
03990 connection->disconnected_message_processed = TRUE;
03991
03992
03993
03994
03995
03996 connection_forget_shared_unlocked (connection);
03997
03998 if (connection->exit_on_disconnect)
03999 {
04000 CONNECTION_UNLOCK (connection);
04001
04002 _dbus_verbose ("Exiting on Disconnected signal\n");
04003 _dbus_exit (1);
04004 _dbus_assert_not_reached ("Call to exit() returned");
04005 }
04006 }
04007
04008
04009 CONNECTION_UNLOCK (connection);
04010
04011 if (changed && function)
04012 {
04013 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04014 connection, new_status,
04015 DISPATCH_STATUS_NAME (new_status));
04016 (* function) (connection, new_status, data);
04017 }
04018
04019 dbus_connection_unref (connection);
04020 }
04021
04047 DBusDispatchStatus
04048 dbus_connection_get_dispatch_status (DBusConnection *connection)
04049 {
04050 DBusDispatchStatus status;
04051
04052 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04053
04054 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04055
04056 CONNECTION_LOCK (connection);
04057
04058 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04059
04060 CONNECTION_UNLOCK (connection);
04061
04062 return status;
04063 }
04064
04068 static DBusHandlerResult
04069 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04070 DBusMessage *message)
04071 {
04072 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04073 {
04074
04075 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04076 }
04077 else if (dbus_message_is_method_call (message,
04078 DBUS_INTERFACE_PEER,
04079 "Ping"))
04080 {
04081 DBusMessage *ret;
04082 dbus_bool_t sent;
04083
04084 ret = dbus_message_new_method_return (message);
04085 if (ret == NULL)
04086 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04087
04088 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04089
04090 dbus_message_unref (ret);
04091
04092 if (!sent)
04093 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04094
04095 return DBUS_HANDLER_RESULT_HANDLED;
04096 }
04097 else if (dbus_message_is_method_call (message,
04098 DBUS_INTERFACE_PEER,
04099 "GetMachineId"))
04100 {
04101 DBusMessage *ret;
04102 dbus_bool_t sent;
04103 DBusString uuid;
04104
04105 ret = dbus_message_new_method_return (message);
04106 if (ret == NULL)
04107 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04108
04109 sent = FALSE;
04110 _dbus_string_init (&uuid);
04111 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04112 {
04113 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04114 if (dbus_message_append_args (ret,
04115 DBUS_TYPE_STRING, &v_STRING,
04116 DBUS_TYPE_INVALID))
04117 {
04118 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04119 }
04120 }
04121 _dbus_string_free (&uuid);
04122
04123 dbus_message_unref (ret);
04124
04125 if (!sent)
04126 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04127
04128 return DBUS_HANDLER_RESULT_HANDLED;
04129 }
04130 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04131 {
04132
04133
04134
04135
04136
04137 DBusMessage *ret;
04138 dbus_bool_t sent;
04139
04140 ret = dbus_message_new_error (message,
04141 DBUS_ERROR_UNKNOWN_METHOD,
04142 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04143 if (ret == NULL)
04144 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04145
04146 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04147
04148 dbus_message_unref (ret);
04149
04150 if (!sent)
04151 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04152
04153 return DBUS_HANDLER_RESULT_HANDLED;
04154 }
04155 else
04156 {
04157 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04158 }
04159 }
04160
04167 static DBusHandlerResult
04168 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04169 DBusMessage *message)
04170 {
04171
04172
04173
04174 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04175 }
04176
04219 DBusDispatchStatus
04220 dbus_connection_dispatch (DBusConnection *connection)
04221 {
04222 DBusMessage *message;
04223 DBusList *link, *filter_list_copy, *message_link;
04224 DBusHandlerResult result;
04225 DBusPendingCall *pending;
04226 dbus_int32_t reply_serial;
04227 DBusDispatchStatus status;
04228
04229 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04230
04231 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04232
04233 CONNECTION_LOCK (connection);
04234 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04235 if (status != DBUS_DISPATCH_DATA_REMAINS)
04236 {
04237
04238 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04239 return status;
04240 }
04241
04242
04243
04244
04245 _dbus_connection_ref_unlocked (connection);
04246
04247 _dbus_connection_acquire_dispatch (connection);
04248 HAVE_LOCK_CHECK (connection);
04249
04250 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04251 if (message_link == NULL)
04252 {
04253
04254
04255 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04256
04257 _dbus_connection_release_dispatch (connection);
04258
04259 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04260
04261 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04262
04263 dbus_connection_unref (connection);
04264
04265 return status;
04266 }
04267
04268 message = message_link->data;
04269
04270 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04271 message,
04272 dbus_message_get_type (message),
04273 dbus_message_get_interface (message) ?
04274 dbus_message_get_interface (message) :
04275 "no interface",
04276 dbus_message_get_member (message) ?
04277 dbus_message_get_member (message) :
04278 "no member",
04279 dbus_message_get_signature (message));
04280
04281 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04282
04283
04284
04285
04286
04287
04288
04289
04290 reply_serial = dbus_message_get_reply_serial (message);
04291 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04292 reply_serial);
04293 if (pending)
04294 {
04295 _dbus_verbose ("Dispatching a pending reply\n");
04296 complete_pending_call_and_unlock (connection, pending, message);
04297 pending = NULL;
04298
04299 CONNECTION_LOCK (connection);
04300 _dbus_verbose ("pending call completed in dispatch\n");
04301 result = DBUS_HANDLER_RESULT_HANDLED;
04302 goto out;
04303 }
04304
04305 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04306 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04307 goto out;
04308
04309 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04310 {
04311 _dbus_connection_release_dispatch (connection);
04312 HAVE_LOCK_CHECK (connection);
04313
04314 _dbus_connection_failed_pop (connection, message_link);
04315
04316
04317 _dbus_connection_update_dispatch_status_and_unlock (connection,
04318 DBUS_DISPATCH_NEED_MEMORY);
04319
04320 if (pending)
04321 dbus_pending_call_unref (pending);
04322 dbus_connection_unref (connection);
04323
04324 return DBUS_DISPATCH_NEED_MEMORY;
04325 }
04326
04327 _dbus_list_foreach (&filter_list_copy,
04328 (DBusForeachFunction)_dbus_message_filter_ref,
04329 NULL);
04330
04331
04332
04333
04334 CONNECTION_UNLOCK (connection);
04335
04336 link = _dbus_list_get_first_link (&filter_list_copy);
04337 while (link != NULL)
04338 {
04339 DBusMessageFilter *filter = link->data;
04340 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04341
04342 if (filter->function == NULL)
04343 {
04344 _dbus_verbose (" filter was removed in a callback function\n");
04345 link = next;
04346 continue;
04347 }
04348
04349 _dbus_verbose (" running filter on message %p\n", message);
04350 result = (* filter->function) (connection, message, filter->user_data);
04351
04352 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04353 break;
04354
04355 link = next;
04356 }
04357
04358 _dbus_list_foreach (&filter_list_copy,
04359 (DBusForeachFunction)_dbus_message_filter_unref,
04360 NULL);
04361 _dbus_list_clear (&filter_list_copy);
04362
04363 CONNECTION_LOCK (connection);
04364
04365 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04366 {
04367 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04368 goto out;
04369 }
04370 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04371 {
04372 _dbus_verbose ("filter handled message in dispatch\n");
04373 goto out;
04374 }
04375
04376
04377
04378
04379 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
04380 message,
04381 dbus_message_get_type (message),
04382 dbus_message_get_interface (message) ?
04383 dbus_message_get_interface (message) :
04384 "no interface",
04385 dbus_message_get_member (message) ?
04386 dbus_message_get_member (message) :
04387 "no member",
04388 dbus_message_get_signature (message));
04389
04390 HAVE_LOCK_CHECK (connection);
04391 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04392 message);
04393
04394 CONNECTION_LOCK (connection);
04395
04396 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04397 {
04398 _dbus_verbose ("object tree handled message in dispatch\n");
04399 goto out;
04400 }
04401
04402 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04403 {
04404 DBusMessage *reply;
04405 DBusString str;
04406 DBusPreallocatedSend *preallocated;
04407
04408 _dbus_verbose (" sending error %s\n",
04409 DBUS_ERROR_UNKNOWN_METHOD);
04410
04411 if (!_dbus_string_init (&str))
04412 {
04413 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04414 _dbus_verbose ("no memory for error string in dispatch\n");
04415 goto out;
04416 }
04417
04418 if (!_dbus_string_append_printf (&str,
04419 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04420 dbus_message_get_member (message),
04421 dbus_message_get_signature (message),
04422 dbus_message_get_interface (message)))
04423 {
04424 _dbus_string_free (&str);
04425 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04426 _dbus_verbose ("no memory for error string in dispatch\n");
04427 goto out;
04428 }
04429
04430 reply = dbus_message_new_error (message,
04431 DBUS_ERROR_UNKNOWN_METHOD,
04432 _dbus_string_get_const_data (&str));
04433 _dbus_string_free (&str);
04434
04435 if (reply == NULL)
04436 {
04437 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04438 _dbus_verbose ("no memory for error reply in dispatch\n");
04439 goto out;
04440 }
04441
04442 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04443
04444 if (preallocated == NULL)
04445 {
04446 dbus_message_unref (reply);
04447 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04448 _dbus_verbose ("no memory for error send in dispatch\n");
04449 goto out;
04450 }
04451
04452 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04453 reply, NULL);
04454
04455 dbus_message_unref (reply);
04456
04457 result = DBUS_HANDLER_RESULT_HANDLED;
04458 }
04459
04460 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04461 dbus_message_get_type (message),
04462 dbus_message_get_interface (message) ?
04463 dbus_message_get_interface (message) :
04464 "no interface",
04465 dbus_message_get_member (message) ?
04466 dbus_message_get_member (message) :
04467 "no member",
04468 dbus_message_get_signature (message),
04469 connection);
04470
04471 out:
04472 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04473 {
04474 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04475
04476
04477
04478
04479
04480 _dbus_connection_putback_message_link_unlocked (connection,
04481 message_link);
04482 }
04483 else
04484 {
04485 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04486
04487 _dbus_list_free_link (message_link);
04488 dbus_message_unref (message);
04489
04490
04491 }
04492
04493 _dbus_connection_release_dispatch (connection);
04494 HAVE_LOCK_CHECK (connection);
04495
04496 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04497 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04498
04499
04500 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04501
04502 dbus_connection_unref (connection);
04503
04504 return status;
04505 }
04506
04566 dbus_bool_t
04567 dbus_connection_set_watch_functions (DBusConnection *connection,
04568 DBusAddWatchFunction add_function,
04569 DBusRemoveWatchFunction remove_function,
04570 DBusWatchToggledFunction toggled_function,
04571 void *data,
04572 DBusFreeFunction free_data_function)
04573 {
04574 dbus_bool_t retval;
04575 DBusWatchList *watches;
04576
04577 _dbus_return_val_if_fail (connection != NULL, FALSE);
04578
04579 CONNECTION_LOCK (connection);
04580
04581 #ifndef DBUS_DISABLE_CHECKS
04582 if (connection->watches == NULL)
04583 {
04584 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04585 _DBUS_FUNCTION_NAME);
04586 return FALSE;
04587 }
04588 #endif
04589
04590
04591 _dbus_connection_ref_unlocked (connection);
04592
04593
04594
04595
04596
04597 watches = connection->watches;
04598 connection->watches = NULL;
04599 CONNECTION_UNLOCK (connection);
04600
04601 retval = _dbus_watch_list_set_functions (watches,
04602 add_function, remove_function,
04603 toggled_function,
04604 data, free_data_function);
04605 CONNECTION_LOCK (connection);
04606 connection->watches = watches;
04607
04608 CONNECTION_UNLOCK (connection);
04609
04610 dbus_connection_unref (connection);
04611
04612 return retval;
04613 }
04614
04648 dbus_bool_t
04649 dbus_connection_set_timeout_functions (DBusConnection *connection,
04650 DBusAddTimeoutFunction add_function,
04651 DBusRemoveTimeoutFunction remove_function,
04652 DBusTimeoutToggledFunction toggled_function,
04653 void *data,
04654 DBusFreeFunction free_data_function)
04655 {
04656 dbus_bool_t retval;
04657 DBusTimeoutList *timeouts;
04658
04659 _dbus_return_val_if_fail (connection != NULL, FALSE);
04660
04661 CONNECTION_LOCK (connection);
04662
04663 #ifndef DBUS_DISABLE_CHECKS
04664 if (connection->timeouts == NULL)
04665 {
04666 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04667 _DBUS_FUNCTION_NAME);
04668 return FALSE;
04669 }
04670 #endif
04671
04672
04673 _dbus_connection_ref_unlocked (connection);
04674
04675 timeouts = connection->timeouts;
04676 connection->timeouts = NULL;
04677 CONNECTION_UNLOCK (connection);
04678
04679 retval = _dbus_timeout_list_set_functions (timeouts,
04680 add_function, remove_function,
04681 toggled_function,
04682 data, free_data_function);
04683 CONNECTION_LOCK (connection);
04684 connection->timeouts = timeouts;
04685
04686 CONNECTION_UNLOCK (connection);
04687
04688 dbus_connection_unref (connection);
04689
04690 return retval;
04691 }
04692
04707 void
04708 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04709 DBusWakeupMainFunction wakeup_main_function,
04710 void *data,
04711 DBusFreeFunction free_data_function)
04712 {
04713 void *old_data;
04714 DBusFreeFunction old_free_data;
04715
04716 _dbus_return_if_fail (connection != NULL);
04717
04718 CONNECTION_LOCK (connection);
04719 old_data = connection->wakeup_main_data;
04720 old_free_data = connection->free_wakeup_main_data;
04721
04722 connection->wakeup_main_function = wakeup_main_function;
04723 connection->wakeup_main_data = data;
04724 connection->free_wakeup_main_data = free_data_function;
04725
04726 CONNECTION_UNLOCK (connection);
04727
04728
04729 if (old_free_data)
04730 (*old_free_data) (old_data);
04731 }
04732
04753 void
04754 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04755 DBusDispatchStatusFunction function,
04756 void *data,
04757 DBusFreeFunction free_data_function)
04758 {
04759 void *old_data;
04760 DBusFreeFunction old_free_data;
04761
04762 _dbus_return_if_fail (connection != NULL);
04763
04764 CONNECTION_LOCK (connection);
04765 old_data = connection->dispatch_status_data;
04766 old_free_data = connection->free_dispatch_status_data;
04767
04768 connection->dispatch_status_function = function;
04769 connection->dispatch_status_data = data;
04770 connection->free_dispatch_status_data = free_data_function;
04771
04772 CONNECTION_UNLOCK (connection);
04773
04774
04775 if (old_free_data)
04776 (*old_free_data) (old_data);
04777 }
04778
04798 dbus_bool_t
04799 dbus_connection_get_unix_fd (DBusConnection *connection,
04800 int *fd)
04801 {
04802 _dbus_return_val_if_fail (connection != NULL, FALSE);
04803 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04804
04805 #ifdef DBUS_WIN
04806
04807 return FALSE;
04808 #endif
04809
04810 return dbus_connection_get_socket(connection, fd);
04811 }
04812
04828 dbus_bool_t
04829 dbus_connection_get_socket(DBusConnection *connection,
04830 int *fd)
04831 {
04832 dbus_bool_t retval;
04833
04834 _dbus_return_val_if_fail (connection != NULL, FALSE);
04835 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04836
04837 CONNECTION_LOCK (connection);
04838
04839 retval = _dbus_transport_get_socket_fd (connection->transport,
04840 fd);
04841
04842 CONNECTION_UNLOCK (connection);
04843
04844 return retval;
04845 }
04846
04847
04870 dbus_bool_t
04871 dbus_connection_get_unix_user (DBusConnection *connection,
04872 unsigned long *uid)
04873 {
04874 dbus_bool_t result;
04875
04876 _dbus_return_val_if_fail (connection != NULL, FALSE);
04877 _dbus_return_val_if_fail (uid != NULL, FALSE);
04878
04879 CONNECTION_LOCK (connection);
04880
04881 if (!_dbus_transport_get_is_authenticated (connection->transport))
04882 result = FALSE;
04883 else
04884 result = _dbus_transport_get_unix_user (connection->transport,
04885 uid);
04886
04887 #ifdef DBUS_WIN
04888 _dbus_assert (!result);
04889 #endif
04890
04891 CONNECTION_UNLOCK (connection);
04892
04893 return result;
04894 }
04895
04906 dbus_bool_t
04907 dbus_connection_get_unix_process_id (DBusConnection *connection,
04908 unsigned long *pid)
04909 {
04910 dbus_bool_t result;
04911
04912 _dbus_return_val_if_fail (connection != NULL, FALSE);
04913 _dbus_return_val_if_fail (pid != NULL, FALSE);
04914
04915 CONNECTION_LOCK (connection);
04916
04917 if (!_dbus_transport_get_is_authenticated (connection->transport))
04918 result = FALSE;
04919 else
04920 result = _dbus_transport_get_unix_process_id (connection->transport,
04921 pid);
04922 #ifdef DBUS_WIN
04923 _dbus_assert (!result);
04924 #endif
04925
04926 CONNECTION_UNLOCK (connection);
04927
04928 return result;
04929 }
04930
04953 void
04954 dbus_connection_set_unix_user_function (DBusConnection *connection,
04955 DBusAllowUnixUserFunction function,
04956 void *data,
04957 DBusFreeFunction free_data_function)
04958 {
04959 void *old_data = NULL;
04960 DBusFreeFunction old_free_function = NULL;
04961
04962 _dbus_return_if_fail (connection != NULL);
04963
04964 CONNECTION_LOCK (connection);
04965 _dbus_transport_set_unix_user_function (connection->transport,
04966 function, data, free_data_function,
04967 &old_data, &old_free_function);
04968 CONNECTION_UNLOCK (connection);
04969
04970 if (old_free_function != NULL)
04971 (* old_free_function) (old_data);
04972 }
04973
05005 dbus_bool_t
05006 dbus_connection_get_windows_user (DBusConnection *connection,
05007 char **windows_sid_p)
05008 {
05009 dbus_bool_t result;
05010
05011 _dbus_return_val_if_fail (connection != NULL, FALSE);
05012 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05013
05014 CONNECTION_LOCK (connection);
05015
05016 if (!_dbus_transport_get_is_authenticated (connection->transport))
05017 result = FALSE;
05018 else
05019 result = _dbus_transport_get_windows_user (connection->transport,
05020 windows_sid_p);
05021
05022 #ifdef DBUS_UNIX
05023 _dbus_assert (!result);
05024 #endif
05025
05026 CONNECTION_UNLOCK (connection);
05027
05028 return result;
05029 }
05030
05052 void
05053 dbus_connection_set_windows_user_function (DBusConnection *connection,
05054 DBusAllowWindowsUserFunction function,
05055 void *data,
05056 DBusFreeFunction free_data_function)
05057 {
05058 void *old_data = NULL;
05059 DBusFreeFunction old_free_function = NULL;
05060
05061 _dbus_return_if_fail (connection != NULL);
05062
05063 CONNECTION_LOCK (connection);
05064 _dbus_transport_set_windows_user_function (connection->transport,
05065 function, data, free_data_function,
05066 &old_data, &old_free_function);
05067 CONNECTION_UNLOCK (connection);
05068
05069 if (old_free_function != NULL)
05070 (* old_free_function) (old_data);
05071 }
05072
05099 void
05100 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05101 dbus_bool_t value)
05102 {
05103 _dbus_return_if_fail (connection != NULL);
05104
05105 CONNECTION_LOCK (connection);
05106 _dbus_transport_set_allow_anonymous (connection->transport, value);
05107 CONNECTION_UNLOCK (connection);
05108 }
05109
05127 void
05128 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05129 dbus_bool_t value)
05130 {
05131 _dbus_return_if_fail (connection != NULL);
05132
05133 CONNECTION_LOCK (connection);
05134 connection->route_peer_messages = TRUE;
05135 CONNECTION_UNLOCK (connection);
05136 }
05137
05159 dbus_bool_t
05160 dbus_connection_add_filter (DBusConnection *connection,
05161 DBusHandleMessageFunction function,
05162 void *user_data,
05163 DBusFreeFunction free_data_function)
05164 {
05165 DBusMessageFilter *filter;
05166
05167 _dbus_return_val_if_fail (connection != NULL, FALSE);
05168 _dbus_return_val_if_fail (function != NULL, FALSE);
05169
05170 filter = dbus_new0 (DBusMessageFilter, 1);
05171 if (filter == NULL)
05172 return FALSE;
05173
05174 filter->refcount.value = 1;
05175
05176 CONNECTION_LOCK (connection);
05177
05178 if (!_dbus_list_append (&connection->filter_list,
05179 filter))
05180 {
05181 _dbus_message_filter_unref (filter);
05182 CONNECTION_UNLOCK (connection);
05183 return FALSE;
05184 }
05185
05186
05187
05188
05189
05190
05191 filter->function = function;
05192 filter->user_data = user_data;
05193 filter->free_user_data_function = free_data_function;
05194
05195 CONNECTION_UNLOCK (connection);
05196 return TRUE;
05197 }
05198
05211 void
05212 dbus_connection_remove_filter (DBusConnection *connection,
05213 DBusHandleMessageFunction function,
05214 void *user_data)
05215 {
05216 DBusList *link;
05217 DBusMessageFilter *filter;
05218
05219 _dbus_return_if_fail (connection != NULL);
05220 _dbus_return_if_fail (function != NULL);
05221
05222 CONNECTION_LOCK (connection);
05223
05224 filter = NULL;
05225
05226 link = _dbus_list_get_last_link (&connection->filter_list);
05227 while (link != NULL)
05228 {
05229 filter = link->data;
05230
05231 if (filter->function == function &&
05232 filter->user_data == user_data)
05233 {
05234 _dbus_list_remove_link (&connection->filter_list, link);
05235 filter->function = NULL;
05236
05237 break;
05238 }
05239
05240 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05241 }
05242
05243 CONNECTION_UNLOCK (connection);
05244
05245 #ifndef DBUS_DISABLE_CHECKS
05246 if (filter == NULL)
05247 {
05248 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05249 function, user_data);
05250 return;
05251 }
05252 #endif
05253
05254
05255 if (filter->free_user_data_function)
05256 (* filter->free_user_data_function) (filter->user_data);
05257
05258 filter->free_user_data_function = NULL;
05259 filter->user_data = NULL;
05260
05261 _dbus_message_filter_unref (filter);
05262 }
05263
05275 dbus_bool_t
05276 dbus_connection_register_object_path (DBusConnection *connection,
05277 const char *path,
05278 const DBusObjectPathVTable *vtable,
05279 void *user_data)
05280 {
05281 char **decomposed_path;
05282 dbus_bool_t retval;
05283
05284 _dbus_return_val_if_fail (connection != NULL, FALSE);
05285 _dbus_return_val_if_fail (path != NULL, FALSE);
05286 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05287 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05288
05289 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05290 return FALSE;
05291
05292 CONNECTION_LOCK (connection);
05293
05294 retval = _dbus_object_tree_register (connection->objects,
05295 FALSE,
05296 (const char **) decomposed_path, vtable,
05297 user_data);
05298
05299 CONNECTION_UNLOCK (connection);
05300
05301 dbus_free_string_array (decomposed_path);
05302
05303 return retval;
05304 }
05305
05318 dbus_bool_t
05319 dbus_connection_register_fallback (DBusConnection *connection,
05320 const char *path,
05321 const DBusObjectPathVTable *vtable,
05322 void *user_data)
05323 {
05324 char **decomposed_path;
05325 dbus_bool_t retval;
05326
05327 _dbus_return_val_if_fail (connection != NULL, FALSE);
05328 _dbus_return_val_if_fail (path != NULL, FALSE);
05329 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05330 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05331
05332 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05333 return FALSE;
05334
05335 CONNECTION_LOCK (connection);
05336
05337 retval = _dbus_object_tree_register (connection->objects,
05338 TRUE,
05339 (const char **) decomposed_path, vtable,
05340 user_data);
05341
05342 CONNECTION_UNLOCK (connection);
05343
05344 dbus_free_string_array (decomposed_path);
05345
05346 return retval;
05347 }
05348
05358 dbus_bool_t
05359 dbus_connection_unregister_object_path (DBusConnection *connection,
05360 const char *path)
05361 {
05362 char **decomposed_path;
05363
05364 _dbus_return_val_if_fail (connection != NULL, FALSE);
05365 _dbus_return_val_if_fail (path != NULL, FALSE);
05366 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05367
05368 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05369 return FALSE;
05370
05371 CONNECTION_LOCK (connection);
05372
05373 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05374
05375 dbus_free_string_array (decomposed_path);
05376
05377 return TRUE;
05378 }
05379
05390 dbus_bool_t
05391 dbus_connection_get_object_path_data (DBusConnection *connection,
05392 const char *path,
05393 void **data_p)
05394 {
05395 char **decomposed_path;
05396
05397 _dbus_return_val_if_fail (connection != NULL, FALSE);
05398 _dbus_return_val_if_fail (path != NULL, FALSE);
05399 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05400
05401 *data_p = NULL;
05402
05403 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05404 return FALSE;
05405
05406 CONNECTION_LOCK (connection);
05407
05408 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05409
05410 CONNECTION_UNLOCK (connection);
05411
05412 dbus_free_string_array (decomposed_path);
05413
05414 return TRUE;
05415 }
05416
05427 dbus_bool_t
05428 dbus_connection_list_registered (DBusConnection *connection,
05429 const char *parent_path,
05430 char ***child_entries)
05431 {
05432 char **decomposed_path;
05433 dbus_bool_t retval;
05434 _dbus_return_val_if_fail (connection != NULL, FALSE);
05435 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05436 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05437 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05438
05439 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05440 return FALSE;
05441
05442 CONNECTION_LOCK (connection);
05443
05444 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05445 (const char **) decomposed_path,
05446 child_entries);
05447 dbus_free_string_array (decomposed_path);
05448
05449 return retval;
05450 }
05451
05452 static DBusDataSlotAllocator slot_allocator;
05453 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05454
05469 dbus_bool_t
05470 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05471 {
05472 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05473 &_DBUS_LOCK_NAME (connection_slots),
05474 slot_p);
05475 }
05476
05488 void
05489 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05490 {
05491 _dbus_return_if_fail (*slot_p >= 0);
05492
05493 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05494 }
05495
05509 dbus_bool_t
05510 dbus_connection_set_data (DBusConnection *connection,
05511 dbus_int32_t slot,
05512 void *data,
05513 DBusFreeFunction free_data_func)
05514 {
05515 DBusFreeFunction old_free_func;
05516 void *old_data;
05517 dbus_bool_t retval;
05518
05519 _dbus_return_val_if_fail (connection != NULL, FALSE);
05520 _dbus_return_val_if_fail (slot >= 0, FALSE);
05521
05522 CONNECTION_LOCK (connection);
05523
05524 retval = _dbus_data_slot_list_set (&slot_allocator,
05525 &connection->slot_list,
05526 slot, data, free_data_func,
05527 &old_free_func, &old_data);
05528
05529 CONNECTION_UNLOCK (connection);
05530
05531 if (retval)
05532 {
05533
05534 if (old_free_func)
05535 (* old_free_func) (old_data);
05536 }
05537
05538 return retval;
05539 }
05540
05549 void*
05550 dbus_connection_get_data (DBusConnection *connection,
05551 dbus_int32_t slot)
05552 {
05553 void *res;
05554
05555 _dbus_return_val_if_fail (connection != NULL, NULL);
05556
05557 CONNECTION_LOCK (connection);
05558
05559 res = _dbus_data_slot_list_get (&slot_allocator,
05560 &connection->slot_list,
05561 slot);
05562
05563 CONNECTION_UNLOCK (connection);
05564
05565 return res;
05566 }
05567
05574 void
05575 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05576 {
05577 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05578 }
05579
05588 void
05589 dbus_connection_set_max_message_size (DBusConnection *connection,
05590 long size)
05591 {
05592 _dbus_return_if_fail (connection != NULL);
05593
05594 CONNECTION_LOCK (connection);
05595 _dbus_transport_set_max_message_size (connection->transport,
05596 size);
05597 CONNECTION_UNLOCK (connection);
05598 }
05599
05606 long
05607 dbus_connection_get_max_message_size (DBusConnection *connection)
05608 {
05609 long res;
05610
05611 _dbus_return_val_if_fail (connection != NULL, 0);
05612
05613 CONNECTION_LOCK (connection);
05614 res = _dbus_transport_get_max_message_size (connection->transport);
05615 CONNECTION_UNLOCK (connection);
05616 return res;
05617 }
05618
05644 void
05645 dbus_connection_set_max_received_size (DBusConnection *connection,
05646 long size)
05647 {
05648 _dbus_return_if_fail (connection != NULL);
05649
05650 CONNECTION_LOCK (connection);
05651 _dbus_transport_set_max_received_size (connection->transport,
05652 size);
05653 CONNECTION_UNLOCK (connection);
05654 }
05655
05662 long
05663 dbus_connection_get_max_received_size (DBusConnection *connection)
05664 {
05665 long res;
05666
05667 _dbus_return_val_if_fail (connection != NULL, 0);
05668
05669 CONNECTION_LOCK (connection);
05670 res = _dbus_transport_get_max_received_size (connection->transport);
05671 CONNECTION_UNLOCK (connection);
05672 return res;
05673 }
05674
05685 long
05686 dbus_connection_get_outgoing_size (DBusConnection *connection)
05687 {
05688 long res;
05689
05690 _dbus_return_val_if_fail (connection != NULL, 0);
05691
05692 CONNECTION_LOCK (connection);
05693 res = _dbus_counter_get_value (connection->outgoing_counter);
05694 CONNECTION_UNLOCK (connection);
05695 return res;
05696 }
05697