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 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
00324 dbus_uint32_t client_serial);
00325
00326 static DBusMessageFilter *
00327 _dbus_message_filter_ref (DBusMessageFilter *filter)
00328 {
00329 _dbus_assert (filter->refcount.value > 0);
00330 _dbus_atomic_inc (&filter->refcount);
00331
00332 return filter;
00333 }
00334
00335 static void
00336 _dbus_message_filter_unref (DBusMessageFilter *filter)
00337 {
00338 _dbus_assert (filter->refcount.value > 0);
00339
00340 if (_dbus_atomic_dec (&filter->refcount) == 1)
00341 {
00342 if (filter->free_user_data_function)
00343 (* filter->free_user_data_function) (filter->user_data);
00344
00345 dbus_free (filter);
00346 }
00347 }
00348
00354 void
00355 _dbus_connection_lock (DBusConnection *connection)
00356 {
00357 CONNECTION_LOCK (connection);
00358 }
00359
00365 void
00366 _dbus_connection_unlock (DBusConnection *connection)
00367 {
00368 CONNECTION_UNLOCK (connection);
00369 }
00370
00378 static void
00379 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00380 {
00381 if (connection->wakeup_main_function)
00382 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00383 }
00384
00385 #ifdef DBUS_BUILD_TESTS
00386
00396 dbus_bool_t
00397 _dbus_connection_queue_received_message (DBusConnection *connection,
00398 DBusMessage *message)
00399 {
00400 DBusList *link;
00401
00402 link = _dbus_list_alloc_link (message);
00403 if (link == NULL)
00404 return FALSE;
00405
00406 dbus_message_ref (message);
00407 _dbus_connection_queue_received_message_link (connection, link);
00408
00409 return TRUE;
00410 }
00411
00424 void
00425 _dbus_connection_test_get_locks (DBusConnection *connection,
00426 DBusMutex **mutex_loc,
00427 DBusMutex **dispatch_mutex_loc,
00428 DBusMutex **io_path_mutex_loc,
00429 DBusCondVar **dispatch_cond_loc,
00430 DBusCondVar **io_path_cond_loc)
00431 {
00432 *mutex_loc = connection->mutex;
00433 *dispatch_mutex_loc = connection->dispatch_mutex;
00434 *io_path_mutex_loc = connection->io_path_mutex;
00435 *dispatch_cond_loc = connection->dispatch_cond;
00436 *io_path_cond_loc = connection->io_path_cond;
00437 }
00438 #endif
00439
00448 void
00449 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00450 DBusList *link)
00451 {
00452 DBusPendingCall *pending;
00453 dbus_uint32_t reply_serial;
00454 DBusMessage *message;
00455
00456 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00457
00458 _dbus_list_append_link (&connection->incoming_messages,
00459 link);
00460 message = link->data;
00461
00462
00463 reply_serial = dbus_message_get_reply_serial (message);
00464 if (reply_serial != 0)
00465 {
00466 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00467 reply_serial);
00468 if (pending != NULL)
00469 {
00470 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00471 _dbus_connection_remove_timeout_unlocked (connection,
00472 _dbus_pending_call_get_timeout_unlocked (pending));
00473
00474 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00475 }
00476 }
00477
00478
00479
00480 connection->n_incoming += 1;
00481
00482 _dbus_connection_wakeup_mainloop (connection);
00483
00484 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00485 message,
00486 dbus_message_get_type (message),
00487 dbus_message_get_path (message) ?
00488 dbus_message_get_path (message) :
00489 "no path",
00490 dbus_message_get_interface (message) ?
00491 dbus_message_get_interface (message) :
00492 "no interface",
00493 dbus_message_get_member (message) ?
00494 dbus_message_get_member (message) :
00495 "no member",
00496 dbus_message_get_signature (message),
00497 dbus_message_get_reply_serial (message),
00498 connection,
00499 connection->n_incoming);}
00500
00509 void
00510 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00511 DBusList *link)
00512 {
00513 HAVE_LOCK_CHECK (connection);
00514
00515 _dbus_list_append_link (&connection->incoming_messages, link);
00516
00517 connection->n_incoming += 1;
00518
00519 _dbus_connection_wakeup_mainloop (connection);
00520
00521 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00522 link->data, connection, connection->n_incoming);
00523 }
00524
00525
00533 dbus_bool_t
00534 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00535 {
00536 HAVE_LOCK_CHECK (connection);
00537 return connection->outgoing_messages != NULL;
00538 }
00539
00549 dbus_bool_t
00550 dbus_connection_has_messages_to_send (DBusConnection *connection)
00551 {
00552 dbus_bool_t v;
00553
00554 _dbus_return_val_if_fail (connection != NULL, FALSE);
00555
00556 CONNECTION_LOCK (connection);
00557 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00558 CONNECTION_UNLOCK (connection);
00559
00560 return v;
00561 }
00562
00570 DBusMessage*
00571 _dbus_connection_get_message_to_send (DBusConnection *connection)
00572 {
00573 HAVE_LOCK_CHECK (connection);
00574
00575 return _dbus_list_get_last (&connection->outgoing_messages);
00576 }
00577
00586 void
00587 _dbus_connection_message_sent (DBusConnection *connection,
00588 DBusMessage *message)
00589 {
00590 DBusList *link;
00591
00592 HAVE_LOCK_CHECK (connection);
00593
00594
00595
00596
00597
00598
00599 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00600 _dbus_assert (link != NULL);
00601 _dbus_assert (link->data == message);
00602
00603
00604 _dbus_list_unlink (&connection->outgoing_messages,
00605 link);
00606 _dbus_list_prepend_link (&connection->link_cache, link);
00607
00608 connection->n_outgoing -= 1;
00609
00610 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00611 message,
00612 dbus_message_get_type (message),
00613 dbus_message_get_path (message) ?
00614 dbus_message_get_path (message) :
00615 "no path",
00616 dbus_message_get_interface (message) ?
00617 dbus_message_get_interface (message) :
00618 "no interface",
00619 dbus_message_get_member (message) ?
00620 dbus_message_get_member (message) :
00621 "no member",
00622 dbus_message_get_signature (message),
00623 connection, connection->n_outgoing);
00624
00625
00626 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00627 &link);
00628 _dbus_list_prepend_link (&connection->link_cache, link);
00629
00630 dbus_message_unref (message);
00631 }
00632
00634 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00635 DBusWatch *watch);
00637 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00638 DBusWatch *watch);
00640 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00641 DBusWatch *watch,
00642 dbus_bool_t enabled);
00643
00644 static dbus_bool_t
00645 protected_change_watch (DBusConnection *connection,
00646 DBusWatch *watch,
00647 DBusWatchAddFunction add_function,
00648 DBusWatchRemoveFunction remove_function,
00649 DBusWatchToggleFunction toggle_function,
00650 dbus_bool_t enabled)
00651 {
00652 DBusWatchList *watches;
00653 dbus_bool_t retval;
00654
00655 HAVE_LOCK_CHECK (connection);
00656
00657
00658
00659
00660
00661 watches = connection->watches;
00662 if (watches)
00663 {
00664 connection->watches = NULL;
00665 _dbus_connection_ref_unlocked (connection);
00666 CONNECTION_UNLOCK (connection);
00667
00668 if (add_function)
00669 retval = (* add_function) (watches, watch);
00670 else if (remove_function)
00671 {
00672 retval = TRUE;
00673 (* remove_function) (watches, watch);
00674 }
00675 else
00676 {
00677 retval = TRUE;
00678 (* toggle_function) (watches, watch, enabled);
00679 }
00680
00681 CONNECTION_LOCK (connection);
00682 connection->watches = watches;
00683 _dbus_connection_unref_unlocked (connection);
00684
00685 return retval;
00686 }
00687 else
00688 return FALSE;
00689 }
00690
00691
00703 dbus_bool_t
00704 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00705 DBusWatch *watch)
00706 {
00707 return protected_change_watch (connection, watch,
00708 _dbus_watch_list_add_watch,
00709 NULL, NULL, FALSE);
00710 }
00711
00721 void
00722 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00723 DBusWatch *watch)
00724 {
00725 protected_change_watch (connection, watch,
00726 NULL,
00727 _dbus_watch_list_remove_watch,
00728 NULL, FALSE);
00729 }
00730
00741 void
00742 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00743 DBusWatch *watch,
00744 dbus_bool_t enabled)
00745 {
00746 _dbus_assert (watch != NULL);
00747
00748 protected_change_watch (connection, watch,
00749 NULL, NULL,
00750 _dbus_watch_list_toggle_watch,
00751 enabled);
00752 }
00753
00755 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00756 DBusTimeout *timeout);
00758 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00759 DBusTimeout *timeout);
00761 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00762 DBusTimeout *timeout,
00763 dbus_bool_t enabled);
00764
00765 static dbus_bool_t
00766 protected_change_timeout (DBusConnection *connection,
00767 DBusTimeout *timeout,
00768 DBusTimeoutAddFunction add_function,
00769 DBusTimeoutRemoveFunction remove_function,
00770 DBusTimeoutToggleFunction toggle_function,
00771 dbus_bool_t enabled)
00772 {
00773 DBusTimeoutList *timeouts;
00774 dbus_bool_t retval;
00775
00776 HAVE_LOCK_CHECK (connection);
00777
00778
00779
00780
00781
00782 timeouts = connection->timeouts;
00783 if (timeouts)
00784 {
00785 connection->timeouts = NULL;
00786 _dbus_connection_ref_unlocked (connection);
00787 CONNECTION_UNLOCK (connection);
00788
00789 if (add_function)
00790 retval = (* add_function) (timeouts, timeout);
00791 else if (remove_function)
00792 {
00793 retval = TRUE;
00794 (* remove_function) (timeouts, timeout);
00795 }
00796 else
00797 {
00798 retval = TRUE;
00799 (* toggle_function) (timeouts, timeout, enabled);
00800 }
00801
00802 CONNECTION_LOCK (connection);
00803 connection->timeouts = timeouts;
00804 _dbus_connection_unref_unlocked (connection);
00805
00806 return retval;
00807 }
00808 else
00809 return FALSE;
00810 }
00811
00824 dbus_bool_t
00825 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00826 DBusTimeout *timeout)
00827 {
00828 return protected_change_timeout (connection, timeout,
00829 _dbus_timeout_list_add_timeout,
00830 NULL, NULL, FALSE);
00831 }
00832
00842 void
00843 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00844 DBusTimeout *timeout)
00845 {
00846 protected_change_timeout (connection, timeout,
00847 NULL,
00848 _dbus_timeout_list_remove_timeout,
00849 NULL, FALSE);
00850 }
00851
00862 void
00863 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00864 DBusTimeout *timeout,
00865 dbus_bool_t enabled)
00866 {
00867 protected_change_timeout (connection, timeout,
00868 NULL, NULL,
00869 _dbus_timeout_list_toggle_timeout,
00870 enabled);
00871 }
00872
00873 static dbus_bool_t
00874 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00875 DBusPendingCall *pending)
00876 {
00877 dbus_uint32_t reply_serial;
00878 DBusTimeout *timeout;
00879
00880 HAVE_LOCK_CHECK (connection);
00881
00882 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00883
00884 _dbus_assert (reply_serial != 0);
00885
00886 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00887
00888 if (timeout)
00889 {
00890 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00891 return FALSE;
00892
00893 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00894 reply_serial,
00895 pending))
00896 {
00897 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00898
00899 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00900 HAVE_LOCK_CHECK (connection);
00901 return FALSE;
00902 }
00903
00904 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00905 }
00906 else
00907 {
00908 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00909 reply_serial,
00910 pending))
00911 {
00912 HAVE_LOCK_CHECK (connection);
00913 return FALSE;
00914 }
00915 }
00916
00917 _dbus_pending_call_ref_unlocked (pending);
00918
00919 HAVE_LOCK_CHECK (connection);
00920
00921 return TRUE;
00922 }
00923
00924 static void
00925 free_pending_call_on_hash_removal (void *data)
00926 {
00927 DBusPendingCall *pending;
00928 DBusConnection *connection;
00929
00930 if (data == NULL)
00931 return;
00932
00933 pending = data;
00934
00935 connection = _dbus_pending_call_get_connection_unlocked (pending);
00936
00937 HAVE_LOCK_CHECK (connection);
00938
00939 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00940 {
00941 _dbus_connection_remove_timeout_unlocked (connection,
00942 _dbus_pending_call_get_timeout_unlocked (pending));
00943
00944 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00945 }
00946
00947
00948
00949
00950
00951
00952 _dbus_connection_ref_unlocked (connection);
00953 _dbus_pending_call_unref_and_unlock (pending);
00954 CONNECTION_LOCK (connection);
00955 _dbus_connection_unref_unlocked (connection);
00956 }
00957
00958 static void
00959 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00960 DBusPendingCall *pending)
00961 {
00962
00963
00964
00965 _dbus_hash_table_remove_int (connection->pending_replies,
00966 _dbus_pending_call_get_reply_serial_unlocked (pending));
00967 }
00968
00969 static void
00970 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00971 DBusPendingCall *pending)
00972 {
00973
00974
00975
00976
00977
00978
00979
00980 _dbus_pending_call_ref_unlocked (pending);
00981 _dbus_hash_table_remove_int (connection->pending_replies,
00982 _dbus_pending_call_get_reply_serial_unlocked (pending));
00983
00984 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00985 _dbus_connection_remove_timeout_unlocked (connection,
00986 _dbus_pending_call_get_timeout_unlocked (pending));
00987
00988 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00989
00990 _dbus_pending_call_unref_and_unlock (pending);
00991 }
00992
01001 void
01002 _dbus_connection_remove_pending_call (DBusConnection *connection,
01003 DBusPendingCall *pending)
01004 {
01005 CONNECTION_LOCK (connection);
01006 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01007 }
01008
01018 static dbus_bool_t
01019 _dbus_connection_acquire_io_path (DBusConnection *connection,
01020 int timeout_milliseconds)
01021 {
01022 dbus_bool_t we_acquired;
01023
01024 HAVE_LOCK_CHECK (connection);
01025
01026
01027 _dbus_connection_ref_unlocked (connection);
01028
01029
01030 CONNECTION_UNLOCK (connection);
01031
01032 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01033 _dbus_mutex_lock (connection->io_path_mutex);
01034
01035 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01036 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01037
01038 we_acquired = FALSE;
01039
01040 if (connection->io_path_acquired)
01041 {
01042 if (timeout_milliseconds != -1)
01043 {
01044 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01045 _DBUS_FUNCTION_NAME, timeout_milliseconds);
01046
01047 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01048 connection->io_path_mutex,
01049 timeout_milliseconds))
01050 {
01051
01052
01053
01054
01055
01056
01057
01058
01059 }
01060 }
01061 else
01062 {
01063 while (connection->io_path_acquired)
01064 {
01065 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01066 _dbus_condvar_wait (connection->io_path_cond,
01067 connection->io_path_mutex);
01068 }
01069 }
01070 }
01071
01072 if (!connection->io_path_acquired)
01073 {
01074 we_acquired = TRUE;
01075 connection->io_path_acquired = TRUE;
01076 }
01077
01078 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01079 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01080
01081 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01082 _dbus_mutex_unlock (connection->io_path_mutex);
01083
01084 CONNECTION_LOCK (connection);
01085
01086 HAVE_LOCK_CHECK (connection);
01087
01088 _dbus_connection_unref_unlocked (connection);
01089
01090 return we_acquired;
01091 }
01092
01100 static void
01101 _dbus_connection_release_io_path (DBusConnection *connection)
01102 {
01103 HAVE_LOCK_CHECK (connection);
01104
01105 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01106 _dbus_mutex_lock (connection->io_path_mutex);
01107
01108 _dbus_assert (connection->io_path_acquired);
01109
01110 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01111 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01112
01113 connection->io_path_acquired = FALSE;
01114 _dbus_condvar_wake_one (connection->io_path_cond);
01115
01116 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01117 _dbus_mutex_unlock (connection->io_path_mutex);
01118 }
01119
01155 void
01156 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01157 DBusPendingCall *pending,
01158 unsigned int flags,
01159 int timeout_milliseconds)
01160 {
01161 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01162
01163 HAVE_LOCK_CHECK (connection);
01164
01165 if (connection->n_outgoing == 0)
01166 flags &= ~DBUS_ITERATION_DO_WRITING;
01167
01168 if (_dbus_connection_acquire_io_path (connection,
01169 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01170 {
01171 HAVE_LOCK_CHECK (connection);
01172
01173 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01174 {
01175 _dbus_verbose ("pending call completed while acquiring I/O path");
01176 }
01177 else if ( (pending != NULL) &&
01178 _dbus_connection_peek_for_reply_unlocked (connection,
01179 _dbus_pending_call_get_reply_serial_unlocked (pending)))
01180 {
01181 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01182 }
01183 else
01184 {
01185 _dbus_transport_do_iteration (connection->transport,
01186 flags, timeout_milliseconds);
01187 }
01188
01189 _dbus_connection_release_io_path (connection);
01190 }
01191
01192 HAVE_LOCK_CHECK (connection);
01193
01194 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01195 }
01196
01206 DBusConnection*
01207 _dbus_connection_new_for_transport (DBusTransport *transport)
01208 {
01209 DBusConnection *connection;
01210 DBusWatchList *watch_list;
01211 DBusTimeoutList *timeout_list;
01212 DBusHashTable *pending_replies;
01213 DBusList *disconnect_link;
01214 DBusMessage *disconnect_message;
01215 DBusCounter *outgoing_counter;
01216 DBusObjectTree *objects;
01217
01218 watch_list = NULL;
01219 connection = NULL;
01220 pending_replies = NULL;
01221 timeout_list = NULL;
01222 disconnect_link = NULL;
01223 disconnect_message = NULL;
01224 outgoing_counter = NULL;
01225 objects = NULL;
01226
01227 watch_list = _dbus_watch_list_new ();
01228 if (watch_list == NULL)
01229 goto error;
01230
01231 timeout_list = _dbus_timeout_list_new ();
01232 if (timeout_list == NULL)
01233 goto error;
01234
01235 pending_replies =
01236 _dbus_hash_table_new (DBUS_HASH_INT,
01237 NULL,
01238 (DBusFreeFunction)free_pending_call_on_hash_removal);
01239 if (pending_replies == NULL)
01240 goto error;
01241
01242 connection = dbus_new0 (DBusConnection, 1);
01243 if (connection == NULL)
01244 goto error;
01245
01246 _dbus_mutex_new_at_location (&connection->mutex);
01247 if (connection->mutex == NULL)
01248 goto error;
01249
01250 _dbus_mutex_new_at_location (&connection->io_path_mutex);
01251 if (connection->io_path_mutex == NULL)
01252 goto error;
01253
01254 _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01255 if (connection->dispatch_mutex == NULL)
01256 goto error;
01257
01258 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01259 if (connection->dispatch_cond == NULL)
01260 goto error;
01261
01262 _dbus_condvar_new_at_location (&connection->io_path_cond);
01263 if (connection->io_path_cond == NULL)
01264 goto error;
01265
01266 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01267 DBUS_INTERFACE_LOCAL,
01268 "Disconnected");
01269
01270 if (disconnect_message == NULL)
01271 goto error;
01272
01273 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01274 if (disconnect_link == NULL)
01275 goto error;
01276
01277 outgoing_counter = _dbus_counter_new ();
01278 if (outgoing_counter == NULL)
01279 goto error;
01280
01281 objects = _dbus_object_tree_new (connection);
01282 if (objects == NULL)
01283 goto error;
01284
01285 if (_dbus_modify_sigpipe)
01286 _dbus_disable_sigpipe ();
01287
01288 connection->refcount.value = 1;
01289 connection->transport = transport;
01290 connection->watches = watch_list;
01291 connection->timeouts = timeout_list;
01292 connection->pending_replies = pending_replies;
01293 connection->outgoing_counter = outgoing_counter;
01294 connection->filter_list = NULL;
01295 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01296 connection->objects = objects;
01297 connection->exit_on_disconnect = FALSE;
01298 connection->shareable = FALSE;
01299 connection->route_peer_messages = FALSE;
01300 connection->disconnected_message_arrived = FALSE;
01301 connection->disconnected_message_processed = FALSE;
01302
01303 #ifndef DBUS_DISABLE_CHECKS
01304 connection->generation = _dbus_current_generation;
01305 #endif
01306
01307 _dbus_data_slot_list_init (&connection->slot_list);
01308
01309 connection->client_serial = 1;
01310
01311 connection->disconnect_message_link = disconnect_link;
01312
01313 CONNECTION_LOCK (connection);
01314
01315 if (!_dbus_transport_set_connection (transport, connection))
01316 {
01317 CONNECTION_UNLOCK (connection);
01318
01319 goto error;
01320 }
01321
01322 _dbus_transport_ref (transport);
01323
01324 CONNECTION_UNLOCK (connection);
01325
01326 return connection;
01327
01328 error:
01329 if (disconnect_message != NULL)
01330 dbus_message_unref (disconnect_message);
01331
01332 if (disconnect_link != NULL)
01333 _dbus_list_free_link (disconnect_link);
01334
01335 if (connection != NULL)
01336 {
01337 _dbus_condvar_free_at_location (&connection->io_path_cond);
01338 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01339 _dbus_mutex_free_at_location (&connection->mutex);
01340 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01341 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01342 dbus_free (connection);
01343 }
01344 if (pending_replies)
01345 _dbus_hash_table_unref (pending_replies);
01346
01347 if (watch_list)
01348 _dbus_watch_list_free (watch_list);
01349
01350 if (timeout_list)
01351 _dbus_timeout_list_free (timeout_list);
01352
01353 if (outgoing_counter)
01354 _dbus_counter_unref (outgoing_counter);
01355
01356 if (objects)
01357 _dbus_object_tree_unref (objects);
01358
01359 return NULL;
01360 }
01361
01369 DBusConnection *
01370 _dbus_connection_ref_unlocked (DBusConnection *connection)
01371 {
01372 _dbus_assert (connection != NULL);
01373 _dbus_assert (connection->generation == _dbus_current_generation);
01374
01375 HAVE_LOCK_CHECK (connection);
01376
01377 #ifdef DBUS_HAVE_ATOMIC_INT
01378 _dbus_atomic_inc (&connection->refcount);
01379 #else
01380 _dbus_assert (connection->refcount.value > 0);
01381 connection->refcount.value += 1;
01382 #endif
01383
01384 return connection;
01385 }
01386
01393 void
01394 _dbus_connection_unref_unlocked (DBusConnection *connection)
01395 {
01396 dbus_bool_t last_unref;
01397
01398 HAVE_LOCK_CHECK (connection);
01399
01400 _dbus_assert (connection != NULL);
01401
01402
01403
01404
01405
01406 #ifdef DBUS_HAVE_ATOMIC_INT
01407 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01408 #else
01409 _dbus_assert (connection->refcount.value > 0);
01410
01411 connection->refcount.value -= 1;
01412 last_unref = (connection->refcount.value == 0);
01413 #if 0
01414 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01415 #endif
01416 #endif
01417
01418 if (last_unref)
01419 _dbus_connection_last_unref (connection);
01420 }
01421
01422 static dbus_uint32_t
01423 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01424 {
01425 dbus_uint32_t serial;
01426
01427 serial = connection->client_serial++;
01428
01429 if (connection->client_serial == 0)
01430 connection->client_serial = 1;
01431
01432 return serial;
01433 }
01434
01448 dbus_bool_t
01449 _dbus_connection_handle_watch (DBusWatch *watch,
01450 unsigned int condition,
01451 void *data)
01452 {
01453 DBusConnection *connection;
01454 dbus_bool_t retval;
01455 DBusDispatchStatus status;
01456
01457 connection = data;
01458
01459 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01460
01461 CONNECTION_LOCK (connection);
01462
01463 if (!_dbus_connection_acquire_io_path (connection, 1))
01464 {
01465
01466 CONNECTION_UNLOCK (connection);
01467 return TRUE;
01468 }
01469
01470 HAVE_LOCK_CHECK (connection);
01471 retval = _dbus_transport_handle_watch (connection->transport,
01472 watch, condition);
01473
01474 _dbus_connection_release_io_path (connection);
01475
01476 HAVE_LOCK_CHECK (connection);
01477
01478 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01479
01480 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01481
01482
01483 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01484
01485 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01486
01487 return retval;
01488 }
01489
01490 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01491 static DBusHashTable *shared_connections = NULL;
01492 static DBusList *shared_connections_no_guid = NULL;
01493
01494 static void
01495 close_connection_on_shutdown (DBusConnection *connection)
01496 {
01497 DBusMessage *message;
01498
01499 dbus_connection_ref (connection);
01500 _dbus_connection_close_possibly_shared (connection);
01501
01502
01503 while ((message = dbus_connection_pop_message (connection)))
01504 {
01505 dbus_message_unref (message);
01506 }
01507 dbus_connection_unref (connection);
01508 }
01509
01510 static void
01511 shared_connections_shutdown (void *data)
01512 {
01513 int n_entries;
01514
01515 _DBUS_LOCK (shared_connections);
01516
01517
01518 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01519 {
01520 DBusConnection *connection;
01521 DBusHashIter iter;
01522
01523 _dbus_hash_iter_init (shared_connections, &iter);
01524 _dbus_hash_iter_next (&iter);
01525
01526 connection = _dbus_hash_iter_get_value (&iter);
01527
01528 _DBUS_UNLOCK (shared_connections);
01529 close_connection_on_shutdown (connection);
01530 _DBUS_LOCK (shared_connections);
01531
01532
01533 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01534 }
01535
01536 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01537
01538 _dbus_hash_table_unref (shared_connections);
01539 shared_connections = NULL;
01540
01541 if (shared_connections_no_guid != NULL)
01542 {
01543 DBusConnection *connection;
01544 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01545 while (connection != NULL)
01546 {
01547 _DBUS_UNLOCK (shared_connections);
01548 close_connection_on_shutdown (connection);
01549 _DBUS_LOCK (shared_connections);
01550 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01551 }
01552 }
01553
01554 shared_connections_no_guid = NULL;
01555
01556 _DBUS_UNLOCK (shared_connections);
01557 }
01558
01559 static dbus_bool_t
01560 connection_lookup_shared (DBusAddressEntry *entry,
01561 DBusConnection **result)
01562 {
01563 _dbus_verbose ("checking for existing connection\n");
01564
01565 *result = NULL;
01566
01567 _DBUS_LOCK (shared_connections);
01568
01569 if (shared_connections == NULL)
01570 {
01571 _dbus_verbose ("creating shared_connections hash table\n");
01572
01573 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01574 dbus_free,
01575 NULL);
01576 if (shared_connections == NULL)
01577 {
01578 _DBUS_UNLOCK (shared_connections);
01579 return FALSE;
01580 }
01581
01582 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01583 {
01584 _dbus_hash_table_unref (shared_connections);
01585 shared_connections = NULL;
01586 _DBUS_UNLOCK (shared_connections);
01587 return FALSE;
01588 }
01589
01590 _dbus_verbose (" successfully created shared_connections\n");
01591
01592 _DBUS_UNLOCK (shared_connections);
01593 return TRUE;
01594 }
01595 else
01596 {
01597 const char *guid;
01598
01599 guid = dbus_address_entry_get_value (entry, "guid");
01600
01601 if (guid != NULL)
01602 {
01603 DBusConnection *connection;
01604
01605 connection = _dbus_hash_table_lookup_string (shared_connections,
01606 guid);
01607
01608 if (connection)
01609 {
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 CONNECTION_LOCK (connection);
01625 if (_dbus_connection_get_is_connected_unlocked (connection))
01626 {
01627 _dbus_connection_ref_unlocked (connection);
01628 *result = connection;
01629 _dbus_verbose ("looked up existing connection to server guid %s\n",
01630 guid);
01631 }
01632 else
01633 {
01634 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01635 guid);
01636 }
01637 CONNECTION_UNLOCK (connection);
01638 }
01639 }
01640
01641 _DBUS_UNLOCK (shared_connections);
01642 return TRUE;
01643 }
01644 }
01645
01646 static dbus_bool_t
01647 connection_record_shared_unlocked (DBusConnection *connection,
01648 const char *guid)
01649 {
01650 char *guid_key;
01651 char *guid_in_connection;
01652
01653 HAVE_LOCK_CHECK (connection);
01654 _dbus_assert (connection->server_guid == NULL);
01655 _dbus_assert (connection->shareable);
01656
01657
01658
01659
01660
01661 _dbus_connection_ref_unlocked (connection);
01662
01663 if (guid == NULL)
01664 {
01665 _DBUS_LOCK (shared_connections);
01666
01667 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01668 {
01669 _DBUS_UNLOCK (shared_connections);
01670 return FALSE;
01671 }
01672
01673 _DBUS_UNLOCK (shared_connections);
01674 return TRUE;
01675 }
01676
01677
01678
01679
01680
01681
01682 guid_key = _dbus_strdup (guid);
01683 if (guid_key == NULL)
01684 return FALSE;
01685
01686 guid_in_connection = _dbus_strdup (guid);
01687 if (guid_in_connection == NULL)
01688 {
01689 dbus_free (guid_key);
01690 return FALSE;
01691 }
01692
01693 _DBUS_LOCK (shared_connections);
01694 _dbus_assert (shared_connections != NULL);
01695
01696 if (!_dbus_hash_table_insert_string (shared_connections,
01697 guid_key, connection))
01698 {
01699 dbus_free (guid_key);
01700 dbus_free (guid_in_connection);
01701 _DBUS_UNLOCK (shared_connections);
01702 return FALSE;
01703 }
01704
01705 connection->server_guid = guid_in_connection;
01706
01707 _dbus_verbose ("stored connection to %s to be shared\n",
01708 connection->server_guid);
01709
01710 _DBUS_UNLOCK (shared_connections);
01711
01712 _dbus_assert (connection->server_guid != NULL);
01713
01714 return TRUE;
01715 }
01716
01717 static void
01718 connection_forget_shared_unlocked (DBusConnection *connection)
01719 {
01720 HAVE_LOCK_CHECK (connection);
01721
01722 if (!connection->shareable)
01723 return;
01724
01725 _DBUS_LOCK (shared_connections);
01726
01727 if (connection->server_guid != NULL)
01728 {
01729 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01730 connection->server_guid);
01731
01732 if (!_dbus_hash_table_remove_string (shared_connections,
01733 connection->server_guid))
01734 _dbus_assert_not_reached ("connection was not in the shared table");
01735
01736 dbus_free (connection->server_guid);
01737 connection->server_guid = NULL;
01738 }
01739 else
01740 {
01741 _dbus_list_remove (&shared_connections_no_guid, connection);
01742 }
01743
01744 _DBUS_UNLOCK (shared_connections);
01745
01746
01747 _dbus_connection_unref_unlocked (connection);
01748 }
01749
01750 static DBusConnection*
01751 connection_try_from_address_entry (DBusAddressEntry *entry,
01752 DBusError *error)
01753 {
01754 DBusTransport *transport;
01755 DBusConnection *connection;
01756
01757 transport = _dbus_transport_open (entry, error);
01758
01759 if (transport == NULL)
01760 {
01761 _DBUS_ASSERT_ERROR_IS_SET (error);
01762 return NULL;
01763 }
01764
01765 connection = _dbus_connection_new_for_transport (transport);
01766
01767 _dbus_transport_unref (transport);
01768
01769 if (connection == NULL)
01770 {
01771 _DBUS_SET_OOM (error);
01772 return NULL;
01773 }
01774
01775 #ifndef DBUS_DISABLE_CHECKS
01776 _dbus_assert (!connection->have_connection_lock);
01777 #endif
01778 return connection;
01779 }
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793 static DBusConnection*
01794 _dbus_connection_open_internal (const char *address,
01795 dbus_bool_t shared,
01796 DBusError *error)
01797 {
01798 DBusConnection *connection;
01799 DBusAddressEntry **entries;
01800 DBusError tmp_error = DBUS_ERROR_INIT;
01801 DBusError first_error = DBUS_ERROR_INIT;
01802 int len, i;
01803
01804 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01805
01806 _dbus_verbose ("opening %s connection to: %s\n",
01807 shared ? "shared" : "private", address);
01808
01809 if (!dbus_parse_address (address, &entries, &len, error))
01810 return NULL;
01811
01812 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01813
01814 connection = NULL;
01815
01816 for (i = 0; i < len; i++)
01817 {
01818 if (shared)
01819 {
01820 if (!connection_lookup_shared (entries[i], &connection))
01821 _DBUS_SET_OOM (&tmp_error);
01822 }
01823
01824 if (connection == NULL)
01825 {
01826 connection = connection_try_from_address_entry (entries[i],
01827 &tmp_error);
01828
01829 if (connection != NULL && shared)
01830 {
01831 const char *guid;
01832
01833 connection->shareable = TRUE;
01834
01835
01836 guid = dbus_address_entry_get_value (entries[i], "guid");
01837
01838 CONNECTION_LOCK (connection);
01839
01840 if (!connection_record_shared_unlocked (connection, guid))
01841 {
01842 _DBUS_SET_OOM (&tmp_error);
01843 _dbus_connection_close_possibly_shared_and_unlock (connection);
01844 dbus_connection_unref (connection);
01845 connection = NULL;
01846 }
01847 else
01848 CONNECTION_UNLOCK (connection);
01849 }
01850 }
01851
01852 if (connection)
01853 break;
01854
01855 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01856
01857 if (i == 0)
01858 dbus_move_error (&tmp_error, &first_error);
01859 else
01860 dbus_error_free (&tmp_error);
01861 }
01862
01863 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01864 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01865
01866 if (connection == NULL)
01867 {
01868 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01869 dbus_move_error (&first_error, error);
01870 }
01871 else
01872 dbus_error_free (&first_error);
01873
01874 dbus_address_entries_free (entries);
01875 return connection;
01876 }
01877
01886 void
01887 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01888 {
01889 _dbus_assert (connection != NULL);
01890 _dbus_assert (connection->generation == _dbus_current_generation);
01891
01892 CONNECTION_LOCK (connection);
01893 _dbus_connection_close_possibly_shared_and_unlock (connection);
01894 }
01895
01896 static DBusPreallocatedSend*
01897 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01898 {
01899 DBusPreallocatedSend *preallocated;
01900
01901 HAVE_LOCK_CHECK (connection);
01902
01903 _dbus_assert (connection != NULL);
01904
01905 preallocated = dbus_new (DBusPreallocatedSend, 1);
01906 if (preallocated == NULL)
01907 return NULL;
01908
01909 if (connection->link_cache != NULL)
01910 {
01911 preallocated->queue_link =
01912 _dbus_list_pop_first_link (&connection->link_cache);
01913 preallocated->queue_link->data = NULL;
01914 }
01915 else
01916 {
01917 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01918 if (preallocated->queue_link == NULL)
01919 goto failed_0;
01920 }
01921
01922 if (connection->link_cache != NULL)
01923 {
01924 preallocated->counter_link =
01925 _dbus_list_pop_first_link (&connection->link_cache);
01926 preallocated->counter_link->data = connection->outgoing_counter;
01927 }
01928 else
01929 {
01930 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01931 if (preallocated->counter_link == NULL)
01932 goto failed_1;
01933 }
01934
01935 _dbus_counter_ref (preallocated->counter_link->data);
01936
01937 preallocated->connection = connection;
01938
01939 return preallocated;
01940
01941 failed_1:
01942 _dbus_list_free_link (preallocated->queue_link);
01943 failed_0:
01944 dbus_free (preallocated);
01945
01946 return NULL;
01947 }
01948
01949
01950 static void
01951 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01952 DBusPreallocatedSend *preallocated,
01953 DBusMessage *message,
01954 dbus_uint32_t *client_serial)
01955 {
01956 dbus_uint32_t serial;
01957 const char *sig;
01958
01959 preallocated->queue_link->data = message;
01960 _dbus_list_prepend_link (&connection->outgoing_messages,
01961 preallocated->queue_link);
01962
01963 _dbus_message_add_size_counter_link (message,
01964 preallocated->counter_link);
01965
01966 dbus_free (preallocated);
01967 preallocated = NULL;
01968
01969 dbus_message_ref (message);
01970
01971 connection->n_outgoing += 1;
01972
01973 sig = dbus_message_get_signature (message);
01974
01975 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01976 message,
01977 dbus_message_get_type (message),
01978 dbus_message_get_path (message) ?
01979 dbus_message_get_path (message) :
01980 "no path",
01981 dbus_message_get_interface (message) ?
01982 dbus_message_get_interface (message) :
01983 "no interface",
01984 dbus_message_get_member (message) ?
01985 dbus_message_get_member (message) :
01986 "no member",
01987 sig,
01988 dbus_message_get_destination (message) ?
01989 dbus_message_get_destination (message) :
01990 "null",
01991 connection,
01992 connection->n_outgoing);
01993
01994 if (dbus_message_get_serial (message) == 0)
01995 {
01996 serial = _dbus_connection_get_next_client_serial (connection);
01997 dbus_message_set_serial (message, serial);
01998 if (client_serial)
01999 *client_serial = serial;
02000 }
02001 else
02002 {
02003 if (client_serial)
02004 *client_serial = dbus_message_get_serial (message);
02005 }
02006
02007 _dbus_verbose ("Message %p serial is %u\n",
02008 message, dbus_message_get_serial (message));
02009
02010 dbus_message_lock (message);
02011
02012
02013
02014
02015 _dbus_connection_do_iteration_unlocked (connection,
02016 NULL,
02017 DBUS_ITERATION_DO_WRITING,
02018 -1);
02019
02020
02021 if (connection->n_outgoing > 0)
02022 _dbus_connection_wakeup_mainloop (connection);
02023 }
02024
02025 static void
02026 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02027 DBusPreallocatedSend *preallocated,
02028 DBusMessage *message,
02029 dbus_uint32_t *client_serial)
02030 {
02031 DBusDispatchStatus status;
02032
02033 HAVE_LOCK_CHECK (connection);
02034
02035 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02036 preallocated,
02037 message, client_serial);
02038
02039 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02040 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02041
02042
02043 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02044 }
02045
02055 dbus_bool_t
02056 _dbus_connection_send_and_unlock (DBusConnection *connection,
02057 DBusMessage *message,
02058 dbus_uint32_t *client_serial)
02059 {
02060 DBusPreallocatedSend *preallocated;
02061
02062 _dbus_assert (connection != NULL);
02063 _dbus_assert (message != NULL);
02064
02065 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02066 if (preallocated == NULL)
02067 {
02068 CONNECTION_UNLOCK (connection);
02069 return FALSE;
02070 }
02071
02072 _dbus_connection_send_preallocated_and_unlock (connection,
02073 preallocated,
02074 message,
02075 client_serial);
02076 return TRUE;
02077 }
02078
02103 void
02104 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02105 {
02106 CONNECTION_LOCK (connection);
02107
02108 _dbus_assert (connection->refcount.value > 0);
02109
02110 if (connection->refcount.value == 1)
02111 _dbus_connection_close_possibly_shared_and_unlock (connection);
02112 else
02113 CONNECTION_UNLOCK (connection);
02114 }
02115
02116
02126 static void
02127 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02128 {
02129 if (timeout_milliseconds == -1)
02130 _dbus_sleep_milliseconds (1000);
02131 else if (timeout_milliseconds < 100)
02132 ;
02133 else if (timeout_milliseconds <= 1000)
02134 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02135 else
02136 _dbus_sleep_milliseconds (1000);
02137 }
02138
02139 static DBusMessage *
02140 generate_local_error_message (dbus_uint32_t serial,
02141 char *error_name,
02142 char *error_msg)
02143 {
02144 DBusMessage *message;
02145 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02146 if (!message)
02147 goto out;
02148
02149 if (!dbus_message_set_error_name (message, error_name))
02150 {
02151 dbus_message_unref (message);
02152 message = NULL;
02153 goto out;
02154 }
02155
02156 dbus_message_set_no_reply (message, TRUE);
02157
02158 if (!dbus_message_set_reply_serial (message,
02159 serial))
02160 {
02161 dbus_message_unref (message);
02162 message = NULL;
02163 goto out;
02164 }
02165
02166 if (error_msg != NULL)
02167 {
02168 DBusMessageIter iter;
02169
02170 dbus_message_iter_init_append (message, &iter);
02171 if (!dbus_message_iter_append_basic (&iter,
02172 DBUS_TYPE_STRING,
02173 &error_msg))
02174 {
02175 dbus_message_unref (message);
02176 message = NULL;
02177 goto out;
02178 }
02179 }
02180
02181 out:
02182 return message;
02183 }
02184
02185
02186
02187
02188 static dbus_bool_t
02189 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02190 dbus_uint32_t client_serial)
02191 {
02192 DBusList *link;
02193 HAVE_LOCK_CHECK (connection);
02194
02195 link = _dbus_list_get_first_link (&connection->incoming_messages);
02196
02197 while (link != NULL)
02198 {
02199 DBusMessage *reply = link->data;
02200
02201 if (dbus_message_get_reply_serial (reply) == client_serial)
02202 {
02203 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02204 return TRUE;
02205 }
02206 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02207 }
02208
02209 return FALSE;
02210 }
02211
02212
02213
02214
02215 static DBusMessage*
02216 check_for_reply_unlocked (DBusConnection *connection,
02217 dbus_uint32_t client_serial)
02218 {
02219 DBusList *link;
02220
02221 HAVE_LOCK_CHECK (connection);
02222
02223 link = _dbus_list_get_first_link (&connection->incoming_messages);
02224
02225 while (link != NULL)
02226 {
02227 DBusMessage *reply = link->data;
02228
02229 if (dbus_message_get_reply_serial (reply) == client_serial)
02230 {
02231 _dbus_list_remove_link (&connection->incoming_messages, link);
02232 connection->n_incoming -= 1;
02233 return reply;
02234 }
02235 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02236 }
02237
02238 return NULL;
02239 }
02240
02241 static void
02242 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02243 {
02244
02245
02246
02247
02248
02249 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02250 {
02251 DBusPendingCall *pending;
02252 DBusHashIter iter;
02253
02254 _dbus_hash_iter_init (connection->pending_replies, &iter);
02255 _dbus_hash_iter_next (&iter);
02256
02257 pending = _dbus_hash_iter_get_value (&iter);
02258 _dbus_pending_call_ref_unlocked (pending);
02259
02260 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02261 connection);
02262
02263 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02264 _dbus_connection_remove_timeout_unlocked (connection,
02265 _dbus_pending_call_get_timeout_unlocked (pending));
02266 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02267 _dbus_hash_iter_remove_entry (&iter);
02268
02269 _dbus_pending_call_unref_and_unlock (pending);
02270 CONNECTION_LOCK (connection);
02271 }
02272 HAVE_LOCK_CHECK (connection);
02273 }
02274
02275 static void
02276 complete_pending_call_and_unlock (DBusConnection *connection,
02277 DBusPendingCall *pending,
02278 DBusMessage *message)
02279 {
02280 _dbus_pending_call_set_reply_unlocked (pending, message);
02281 _dbus_pending_call_ref_unlocked (pending);
02282 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02283
02284
02285 _dbus_pending_call_complete (pending);
02286 dbus_pending_call_unref (pending);
02287 }
02288
02289 static dbus_bool_t
02290 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02291 DBusPendingCall *pending)
02292 {
02293 DBusMessage *reply;
02294 DBusDispatchStatus status;
02295
02296 reply = check_for_reply_unlocked (connection,
02297 _dbus_pending_call_get_reply_serial_unlocked (pending));
02298 if (reply != NULL)
02299 {
02300 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02301
02302 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02303
02304 complete_pending_call_and_unlock (connection, pending, reply);
02305 dbus_message_unref (reply);
02306
02307 CONNECTION_LOCK (connection);
02308 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02309 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02310 dbus_pending_call_unref (pending);
02311
02312 return TRUE;
02313 }
02314
02315 return FALSE;
02316 }
02317
02332 void
02333 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02334 {
02335 long start_tv_sec, start_tv_usec;
02336 long tv_sec, tv_usec;
02337 DBusDispatchStatus status;
02338 DBusConnection *connection;
02339 dbus_uint32_t client_serial;
02340 DBusTimeout *timeout;
02341 int timeout_milliseconds, elapsed_milliseconds;
02342
02343 _dbus_assert (pending != NULL);
02344
02345 if (dbus_pending_call_get_completed (pending))
02346 return;
02347
02348 dbus_pending_call_ref (pending);
02349
02350 connection = _dbus_pending_call_get_connection_and_lock (pending);
02351
02352
02353 _dbus_connection_flush_unlocked (connection);
02354
02355 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02356
02357
02358
02359
02360
02361 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02362 if (timeout)
02363 {
02364 timeout_milliseconds = dbus_timeout_get_interval (timeout);
02365 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02366
02367 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02368 timeout_milliseconds,
02369 client_serial,
02370 start_tv_sec, start_tv_usec);
02371 }
02372 else
02373 {
02374 timeout_milliseconds = -1;
02375
02376 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02377 }
02378
02379
02380
02381 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02382 return;
02383
02384
02385
02386 _dbus_connection_do_iteration_unlocked (connection,
02387 pending,
02388 DBUS_ITERATION_DO_READING |
02389 DBUS_ITERATION_BLOCK,
02390 timeout_milliseconds);
02391
02392 recheck_status:
02393
02394 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02395
02396 HAVE_LOCK_CHECK (connection);
02397
02398
02399
02400 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02401
02402
02403
02404
02405 if (_dbus_pending_call_get_completed_unlocked (pending))
02406 {
02407 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02408 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02409 dbus_pending_call_unref (pending);
02410 return;
02411 }
02412
02413 if (status == DBUS_DISPATCH_DATA_REMAINS)
02414 {
02415 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02416 return;
02417 }
02418
02419 _dbus_get_current_time (&tv_sec, &tv_usec);
02420 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02421 (tv_usec - start_tv_usec) / 1000;
02422
02423 if (!_dbus_connection_get_is_connected_unlocked (connection))
02424 {
02425 DBusMessage *error_msg;
02426
02427 error_msg = generate_local_error_message (client_serial,
02428 DBUS_ERROR_DISCONNECTED,
02429 "Connection was disconnected before a reply was received");
02430
02431
02432 complete_pending_call_and_unlock (connection, pending, error_msg);
02433 dbus_pending_call_unref (pending);
02434 return;
02435 }
02436 else if (connection->disconnect_message_link == NULL)
02437 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02438 else if (timeout == NULL)
02439 {
02440 if (status == DBUS_DISPATCH_NEED_MEMORY)
02441 {
02442
02443
02444
02445
02446 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02447
02448 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02449 }
02450 else
02451 {
02452
02453 _dbus_connection_do_iteration_unlocked (connection,
02454 pending,
02455 DBUS_ITERATION_DO_READING |
02456 DBUS_ITERATION_BLOCK,
02457 timeout_milliseconds - elapsed_milliseconds);
02458 }
02459
02460 goto recheck_status;
02461 }
02462 else if (tv_sec < start_tv_sec)
02463 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02464 else if (elapsed_milliseconds < timeout_milliseconds)
02465 {
02466 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02467
02468 if (status == DBUS_DISPATCH_NEED_MEMORY)
02469 {
02470
02471
02472
02473
02474 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02475
02476 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02477 }
02478 else
02479 {
02480
02481 _dbus_connection_do_iteration_unlocked (connection,
02482 NULL,
02483 DBUS_ITERATION_DO_READING |
02484 DBUS_ITERATION_BLOCK,
02485 timeout_milliseconds - elapsed_milliseconds);
02486 }
02487
02488 goto recheck_status;
02489 }
02490
02491 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02492 elapsed_milliseconds);
02493
02494 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02495
02496
02497 complete_pending_call_and_unlock (connection, pending, NULL);
02498
02499
02500 CONNECTION_LOCK (connection);
02501 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02502 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02503 dbus_pending_call_unref (pending);
02504 }
02505
02542 DBusConnection*
02543 dbus_connection_open (const char *address,
02544 DBusError *error)
02545 {
02546 DBusConnection *connection;
02547
02548 _dbus_return_val_if_fail (address != NULL, NULL);
02549 _dbus_return_val_if_error_is_set (error, NULL);
02550
02551 connection = _dbus_connection_open_internal (address,
02552 TRUE,
02553 error);
02554
02555 return connection;
02556 }
02557
02585 DBusConnection*
02586 dbus_connection_open_private (const char *address,
02587 DBusError *error)
02588 {
02589 DBusConnection *connection;
02590
02591 _dbus_return_val_if_fail (address != NULL, NULL);
02592 _dbus_return_val_if_error_is_set (error, NULL);
02593
02594 connection = _dbus_connection_open_internal (address,
02595 FALSE,
02596 error);
02597
02598 return connection;
02599 }
02600
02607 DBusConnection *
02608 dbus_connection_ref (DBusConnection *connection)
02609 {
02610 _dbus_return_val_if_fail (connection != NULL, NULL);
02611 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02612
02613
02614
02615
02616
02617 #ifdef DBUS_HAVE_ATOMIC_INT
02618 _dbus_atomic_inc (&connection->refcount);
02619 #else
02620 CONNECTION_LOCK (connection);
02621 _dbus_assert (connection->refcount.value > 0);
02622
02623 connection->refcount.value += 1;
02624 CONNECTION_UNLOCK (connection);
02625 #endif
02626
02627 return connection;
02628 }
02629
02630 static void
02631 free_outgoing_message (void *element,
02632 void *data)
02633 {
02634 DBusMessage *message = element;
02635 DBusConnection *connection = data;
02636
02637 _dbus_message_remove_size_counter (message,
02638 connection->outgoing_counter,
02639 NULL);
02640 dbus_message_unref (message);
02641 }
02642
02643
02644
02645
02646
02647 static void
02648 _dbus_connection_last_unref (DBusConnection *connection)
02649 {
02650 DBusList *link;
02651
02652 _dbus_verbose ("Finalizing connection %p\n", connection);
02653
02654 _dbus_assert (connection->refcount.value == 0);
02655
02656
02657
02658
02659 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02660 _dbus_assert (connection->server_guid == NULL);
02661
02662
02663 _dbus_object_tree_free_all_unlocked (connection->objects);
02664
02665 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02666 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02667 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02668
02669 _dbus_watch_list_free (connection->watches);
02670 connection->watches = NULL;
02671
02672 _dbus_timeout_list_free (connection->timeouts);
02673 connection->timeouts = NULL;
02674
02675 _dbus_data_slot_list_free (&connection->slot_list);
02676
02677 link = _dbus_list_get_first_link (&connection->filter_list);
02678 while (link != NULL)
02679 {
02680 DBusMessageFilter *filter = link->data;
02681 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02682
02683 filter->function = NULL;
02684 _dbus_message_filter_unref (filter);
02685 link->data = NULL;
02686
02687 link = next;
02688 }
02689 _dbus_list_clear (&connection->filter_list);
02690
02691
02692
02693 _dbus_object_tree_unref (connection->objects);
02694
02695 _dbus_hash_table_unref (connection->pending_replies);
02696 connection->pending_replies = NULL;
02697
02698 _dbus_list_clear (&connection->filter_list);
02699
02700 _dbus_list_foreach (&connection->outgoing_messages,
02701 free_outgoing_message,
02702 connection);
02703 _dbus_list_clear (&connection->outgoing_messages);
02704
02705 _dbus_list_foreach (&connection->incoming_messages,
02706 (DBusForeachFunction) dbus_message_unref,
02707 NULL);
02708 _dbus_list_clear (&connection->incoming_messages);
02709
02710 _dbus_counter_unref (connection->outgoing_counter);
02711
02712 _dbus_transport_unref (connection->transport);
02713
02714 if (connection->disconnect_message_link)
02715 {
02716 DBusMessage *message = connection->disconnect_message_link->data;
02717 dbus_message_unref (message);
02718 _dbus_list_free_link (connection->disconnect_message_link);
02719 }
02720
02721 _dbus_list_clear (&connection->link_cache);
02722
02723 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02724 _dbus_condvar_free_at_location (&connection->io_path_cond);
02725
02726 _dbus_mutex_free_at_location (&connection->io_path_mutex);
02727 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02728
02729 _dbus_mutex_free_at_location (&connection->mutex);
02730
02731 dbus_free (connection);
02732 }
02733
02753 void
02754 dbus_connection_unref (DBusConnection *connection)
02755 {
02756 dbus_bool_t last_unref;
02757
02758 _dbus_return_if_fail (connection != NULL);
02759 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02760
02761
02762
02763
02764
02765 #ifdef DBUS_HAVE_ATOMIC_INT
02766 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02767 #else
02768 CONNECTION_LOCK (connection);
02769
02770 _dbus_assert (connection->refcount.value > 0);
02771
02772 connection->refcount.value -= 1;
02773 last_unref = (connection->refcount.value == 0);
02774
02775 #if 0
02776 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02777 #endif
02778
02779 CONNECTION_UNLOCK (connection);
02780 #endif
02781
02782 if (last_unref)
02783 {
02784 #ifndef DBUS_DISABLE_CHECKS
02785 if (_dbus_transport_get_is_connected (connection->transport))
02786 {
02787 _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",
02788 connection->shareable ?
02789 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02790 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02791 return;
02792 }
02793 #endif
02794 _dbus_connection_last_unref (connection);
02795 }
02796 }
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807 static void
02808 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02809 {
02810 DBusDispatchStatus status;
02811
02812 HAVE_LOCK_CHECK (connection);
02813
02814 _dbus_verbose ("Disconnecting %p\n", connection);
02815
02816
02817
02818
02819
02820 _dbus_connection_ref_unlocked (connection);
02821
02822 _dbus_transport_disconnect (connection->transport);
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02834
02835
02836 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02837
02838
02839 dbus_connection_unref (connection);
02840 }
02841
02884 void
02885 dbus_connection_close (DBusConnection *connection)
02886 {
02887 _dbus_return_if_fail (connection != NULL);
02888 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02889
02890 CONNECTION_LOCK (connection);
02891
02892 #ifndef DBUS_DISABLE_CHECKS
02893 if (connection->shareable)
02894 {
02895 CONNECTION_UNLOCK (connection);
02896
02897 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02898 return;
02899 }
02900 #endif
02901
02902 _dbus_connection_close_possibly_shared_and_unlock (connection);
02903 }
02904
02905 static dbus_bool_t
02906 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02907 {
02908 HAVE_LOCK_CHECK (connection);
02909 return _dbus_transport_get_is_connected (connection->transport);
02910 }
02911
02925 dbus_bool_t
02926 dbus_connection_get_is_connected (DBusConnection *connection)
02927 {
02928 dbus_bool_t res;
02929
02930 _dbus_return_val_if_fail (connection != NULL, FALSE);
02931
02932 CONNECTION_LOCK (connection);
02933 res = _dbus_connection_get_is_connected_unlocked (connection);
02934 CONNECTION_UNLOCK (connection);
02935
02936 return res;
02937 }
02938
02947 dbus_bool_t
02948 dbus_connection_get_is_authenticated (DBusConnection *connection)
02949 {
02950 dbus_bool_t res;
02951
02952 _dbus_return_val_if_fail (connection != NULL, FALSE);
02953
02954 CONNECTION_LOCK (connection);
02955 res = _dbus_transport_get_is_authenticated (connection->transport);
02956 CONNECTION_UNLOCK (connection);
02957
02958 return res;
02959 }
02960
02981 dbus_bool_t
02982 dbus_connection_get_is_anonymous (DBusConnection *connection)
02983 {
02984 dbus_bool_t res;
02985
02986 _dbus_return_val_if_fail (connection != NULL, FALSE);
02987
02988 CONNECTION_LOCK (connection);
02989 res = _dbus_transport_get_is_anonymous (connection->transport);
02990 CONNECTION_UNLOCK (connection);
02991
02992 return res;
02993 }
02994
03026 char*
03027 dbus_connection_get_server_id (DBusConnection *connection)
03028 {
03029 char *id;
03030
03031 _dbus_return_val_if_fail (connection != NULL, NULL);
03032
03033 CONNECTION_LOCK (connection);
03034 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03035 CONNECTION_UNLOCK (connection);
03036
03037 return id;
03038 }
03039
03053 void
03054 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03055 dbus_bool_t exit_on_disconnect)
03056 {
03057 _dbus_return_if_fail (connection != NULL);
03058
03059 CONNECTION_LOCK (connection);
03060 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03061 CONNECTION_UNLOCK (connection);
03062 }
03063
03073 DBusPreallocatedSend*
03074 dbus_connection_preallocate_send (DBusConnection *connection)
03075 {
03076 DBusPreallocatedSend *preallocated;
03077
03078 _dbus_return_val_if_fail (connection != NULL, NULL);
03079
03080 CONNECTION_LOCK (connection);
03081
03082 preallocated =
03083 _dbus_connection_preallocate_send_unlocked (connection);
03084
03085 CONNECTION_UNLOCK (connection);
03086
03087 return preallocated;
03088 }
03089
03099 void
03100 dbus_connection_free_preallocated_send (DBusConnection *connection,
03101 DBusPreallocatedSend *preallocated)
03102 {
03103 _dbus_return_if_fail (connection != NULL);
03104 _dbus_return_if_fail (preallocated != NULL);
03105 _dbus_return_if_fail (connection == preallocated->connection);
03106
03107 _dbus_list_free_link (preallocated->queue_link);
03108 _dbus_counter_unref (preallocated->counter_link->data);
03109 _dbus_list_free_link (preallocated->counter_link);
03110 dbus_free (preallocated);
03111 }
03112
03125 void
03126 dbus_connection_send_preallocated (DBusConnection *connection,
03127 DBusPreallocatedSend *preallocated,
03128 DBusMessage *message,
03129 dbus_uint32_t *client_serial)
03130 {
03131 _dbus_return_if_fail (connection != NULL);
03132 _dbus_return_if_fail (preallocated != NULL);
03133 _dbus_return_if_fail (message != NULL);
03134 _dbus_return_if_fail (preallocated->connection == connection);
03135 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03136 dbus_message_get_member (message) != NULL);
03137 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03138 (dbus_message_get_interface (message) != NULL &&
03139 dbus_message_get_member (message) != NULL));
03140
03141 CONNECTION_LOCK (connection);
03142 _dbus_connection_send_preallocated_and_unlock (connection,
03143 preallocated,
03144 message, client_serial);
03145 }
03146
03147 static dbus_bool_t
03148 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03149 DBusMessage *message,
03150 dbus_uint32_t *client_serial)
03151 {
03152 DBusPreallocatedSend *preallocated;
03153
03154 _dbus_assert (connection != NULL);
03155 _dbus_assert (message != NULL);
03156
03157 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03158 if (preallocated == NULL)
03159 return FALSE;
03160
03161 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03162 preallocated,
03163 message,
03164 client_serial);
03165 return TRUE;
03166 }
03167
03195 dbus_bool_t
03196 dbus_connection_send (DBusConnection *connection,
03197 DBusMessage *message,
03198 dbus_uint32_t *serial)
03199 {
03200 _dbus_return_val_if_fail (connection != NULL, FALSE);
03201 _dbus_return_val_if_fail (message != NULL, FALSE);
03202
03203 CONNECTION_LOCK (connection);
03204
03205 return _dbus_connection_send_and_unlock (connection,
03206 message,
03207 serial);
03208 }
03209
03210 static dbus_bool_t
03211 reply_handler_timeout (void *data)
03212 {
03213 DBusConnection *connection;
03214 DBusDispatchStatus status;
03215 DBusPendingCall *pending = data;
03216
03217 connection = _dbus_pending_call_get_connection_and_lock (pending);
03218
03219 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03220 connection);
03221 _dbus_connection_remove_timeout_unlocked (connection,
03222 _dbus_pending_call_get_timeout_unlocked (pending));
03223 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03224
03225 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03226 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03227
03228
03229 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03230
03231 return TRUE;
03232 }
03233
03269 dbus_bool_t
03270 dbus_connection_send_with_reply (DBusConnection *connection,
03271 DBusMessage *message,
03272 DBusPendingCall **pending_return,
03273 int timeout_milliseconds)
03274 {
03275 DBusPendingCall *pending;
03276 dbus_int32_t serial = -1;
03277 DBusDispatchStatus status;
03278
03279 _dbus_return_val_if_fail (connection != NULL, FALSE);
03280 _dbus_return_val_if_fail (message != NULL, FALSE);
03281 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03282
03283 if (pending_return)
03284 *pending_return = NULL;
03285
03286 CONNECTION_LOCK (connection);
03287
03288 if (!_dbus_connection_get_is_connected_unlocked (connection))
03289 {
03290 CONNECTION_UNLOCK (connection);
03291
03292 return TRUE;
03293 }
03294
03295 pending = _dbus_pending_call_new_unlocked (connection,
03296 timeout_milliseconds,
03297 reply_handler_timeout);
03298
03299 if (pending == NULL)
03300 {
03301 CONNECTION_UNLOCK (connection);
03302 return FALSE;
03303 }
03304
03305
03306 serial = dbus_message_get_serial (message);
03307 if (serial == 0)
03308 {
03309 serial = _dbus_connection_get_next_client_serial (connection);
03310 dbus_message_set_serial (message, serial);
03311 }
03312
03313 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03314 goto error;
03315
03316
03317
03318
03319
03320 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03321 pending))
03322 goto error;
03323
03324 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03325 {
03326 _dbus_connection_detach_pending_call_and_unlock (connection,
03327 pending);
03328 goto error_unlocked;
03329 }
03330
03331 if (pending_return)
03332 *pending_return = pending;
03333 else
03334 {
03335 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03336
03337
03338
03339 }
03340
03341 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03342
03343
03344 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03345
03346 if (pending_return == NULL)
03347 dbus_pending_call_unref (pending);
03348
03349 return TRUE;
03350
03351 error:
03352 CONNECTION_UNLOCK (connection);
03353 error_unlocked:
03354 dbus_pending_call_unref (pending);
03355 return FALSE;
03356 }
03357
03388 DBusMessage*
03389 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03390 DBusMessage *message,
03391 int timeout_milliseconds,
03392 DBusError *error)
03393 {
03394 DBusMessage *reply;
03395 DBusPendingCall *pending;
03396
03397 _dbus_return_val_if_fail (connection != NULL, NULL);
03398 _dbus_return_val_if_fail (message != NULL, NULL);
03399 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03400 _dbus_return_val_if_error_is_set (error, NULL);
03401
03402 if (!dbus_connection_send_with_reply (connection, message,
03403 &pending, timeout_milliseconds))
03404 {
03405 _DBUS_SET_OOM (error);
03406 return NULL;
03407 }
03408
03409 if (pending == NULL)
03410 {
03411 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03412 return NULL;
03413 }
03414
03415 dbus_pending_call_block (pending);
03416
03417 reply = dbus_pending_call_steal_reply (pending);
03418 dbus_pending_call_unref (pending);
03419
03420
03421
03422
03423 _dbus_assert (reply != NULL);
03424
03425 if (dbus_set_error_from_message (error, reply))
03426 {
03427 dbus_message_unref (reply);
03428 return NULL;
03429 }
03430 else
03431 return reply;
03432 }
03433
03442 static DBusDispatchStatus
03443 _dbus_connection_flush_unlocked (DBusConnection *connection)
03444 {
03445
03446
03447
03448
03449
03450 DBusDispatchStatus status;
03451
03452 HAVE_LOCK_CHECK (connection);
03453
03454 while (connection->n_outgoing > 0 &&
03455 _dbus_connection_get_is_connected_unlocked (connection))
03456 {
03457 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03458 HAVE_LOCK_CHECK (connection);
03459 _dbus_connection_do_iteration_unlocked (connection,
03460 NULL,
03461 DBUS_ITERATION_DO_READING |
03462 DBUS_ITERATION_DO_WRITING |
03463 DBUS_ITERATION_BLOCK,
03464 -1);
03465 }
03466
03467 HAVE_LOCK_CHECK (connection);
03468 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03469 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03470
03471 HAVE_LOCK_CHECK (connection);
03472 return status;
03473 }
03474
03480 void
03481 dbus_connection_flush (DBusConnection *connection)
03482 {
03483
03484
03485
03486
03487
03488 DBusDispatchStatus status;
03489
03490 _dbus_return_if_fail (connection != NULL);
03491
03492 CONNECTION_LOCK (connection);
03493
03494 status = _dbus_connection_flush_unlocked (connection);
03495
03496 HAVE_LOCK_CHECK (connection);
03497
03498 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03499
03500 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03501 }
03502
03513 static dbus_bool_t
03514 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03515 int timeout_milliseconds,
03516 dbus_bool_t dispatch)
03517 {
03518 DBusDispatchStatus dstatus;
03519 dbus_bool_t progress_possible;
03520
03521
03522
03523
03524
03525 dbus_connection_ref (connection);
03526 dstatus = dbus_connection_get_dispatch_status (connection);
03527
03528 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03529 {
03530 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03531 dbus_connection_dispatch (connection);
03532 CONNECTION_LOCK (connection);
03533 }
03534 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03535 {
03536 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03537 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03538 CONNECTION_LOCK (connection);
03539 }
03540 else
03541 {
03542 CONNECTION_LOCK (connection);
03543 if (_dbus_connection_get_is_connected_unlocked (connection))
03544 {
03545 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03546 _dbus_connection_do_iteration_unlocked (connection,
03547 NULL,
03548 DBUS_ITERATION_DO_READING |
03549 DBUS_ITERATION_DO_WRITING |
03550 DBUS_ITERATION_BLOCK,
03551 timeout_milliseconds);
03552 }
03553 }
03554
03555 HAVE_LOCK_CHECK (connection);
03556
03557
03558
03559
03560 if (dispatch)
03561 progress_possible = connection->n_incoming != 0 ||
03562 connection->disconnect_message_link != NULL;
03563 else
03564 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03565
03566 CONNECTION_UNLOCK (connection);
03567
03568 dbus_connection_unref (connection);
03569
03570 return progress_possible;
03571 }
03572
03573
03608 dbus_bool_t
03609 dbus_connection_read_write_dispatch (DBusConnection *connection,
03610 int timeout_milliseconds)
03611 {
03612 _dbus_return_val_if_fail (connection != NULL, FALSE);
03613 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03614 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03615 }
03616
03640 dbus_bool_t
03641 dbus_connection_read_write (DBusConnection *connection,
03642 int timeout_milliseconds)
03643 {
03644 _dbus_return_val_if_fail (connection != NULL, FALSE);
03645 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03646 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03647 }
03648
03649
03650
03651
03652
03653
03654 static void
03655 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03656 DBusMessage *head_of_queue)
03657 {
03658 HAVE_LOCK_CHECK (connection);
03659
03660
03661 if (connection->disconnect_message_link == NULL &&
03662 dbus_message_is_signal (head_of_queue,
03663 DBUS_INTERFACE_LOCAL,
03664 "Disconnected"))
03665 {
03666 connection->disconnected_message_arrived = TRUE;
03667 }
03668 }
03669
03689 DBusMessage*
03690 dbus_connection_borrow_message (DBusConnection *connection)
03691 {
03692 DBusDispatchStatus status;
03693 DBusMessage *message;
03694
03695 _dbus_return_val_if_fail (connection != NULL, NULL);
03696
03697 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03698
03699
03700
03701
03702 status = dbus_connection_get_dispatch_status (connection);
03703 if (status != DBUS_DISPATCH_DATA_REMAINS)
03704 return NULL;
03705
03706 CONNECTION_LOCK (connection);
03707
03708 _dbus_connection_acquire_dispatch (connection);
03709
03710
03711 _dbus_assert (connection->message_borrowed == NULL);
03712
03713 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03714
03715 message = connection->message_borrowed;
03716
03717 check_disconnected_message_arrived_unlocked (connection, message);
03718
03719
03720 if (message == NULL)
03721 _dbus_connection_release_dispatch (connection);
03722
03723 CONNECTION_UNLOCK (connection);
03724
03725
03726
03727 return message;
03728 }
03729
03738 void
03739 dbus_connection_return_message (DBusConnection *connection,
03740 DBusMessage *message)
03741 {
03742 DBusDispatchStatus status;
03743
03744 _dbus_return_if_fail (connection != NULL);
03745 _dbus_return_if_fail (message != NULL);
03746 _dbus_return_if_fail (message == connection->message_borrowed);
03747 _dbus_return_if_fail (connection->dispatch_acquired);
03748
03749 CONNECTION_LOCK (connection);
03750
03751 _dbus_assert (message == connection->message_borrowed);
03752
03753 connection->message_borrowed = NULL;
03754
03755 _dbus_connection_release_dispatch (connection);
03756
03757 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03758 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03759 }
03760
03770 void
03771 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03772 DBusMessage *message)
03773 {
03774 DBusMessage *pop_message;
03775 DBusDispatchStatus status;
03776
03777 _dbus_return_if_fail (connection != NULL);
03778 _dbus_return_if_fail (message != NULL);
03779 _dbus_return_if_fail (message == connection->message_borrowed);
03780 _dbus_return_if_fail (connection->dispatch_acquired);
03781
03782 CONNECTION_LOCK (connection);
03783
03784 _dbus_assert (message == connection->message_borrowed);
03785
03786 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03787 _dbus_assert (message == pop_message);
03788
03789 connection->n_incoming -= 1;
03790
03791 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03792 message, connection->n_incoming);
03793
03794 connection->message_borrowed = NULL;
03795
03796 _dbus_connection_release_dispatch (connection);
03797
03798 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03799 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03800 }
03801
03802
03803
03804
03805 static DBusList*
03806 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03807 {
03808 HAVE_LOCK_CHECK (connection);
03809
03810 _dbus_assert (connection->message_borrowed == NULL);
03811
03812 if (connection->n_incoming > 0)
03813 {
03814 DBusList *link;
03815
03816 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03817 connection->n_incoming -= 1;
03818
03819 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03820 link->data,
03821 dbus_message_get_type (link->data),
03822 dbus_message_get_path (link->data) ?
03823 dbus_message_get_path (link->data) :
03824 "no path",
03825 dbus_message_get_interface (link->data) ?
03826 dbus_message_get_interface (link->data) :
03827 "no interface",
03828 dbus_message_get_member (link->data) ?
03829 dbus_message_get_member (link->data) :
03830 "no member",
03831 dbus_message_get_signature (link->data),
03832 connection, connection->n_incoming);
03833
03834 check_disconnected_message_arrived_unlocked (connection, link->data);
03835
03836 return link;
03837 }
03838 else
03839 return NULL;
03840 }
03841
03842
03843
03844
03845 static DBusMessage*
03846 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03847 {
03848 DBusList *link;
03849
03850 HAVE_LOCK_CHECK (connection);
03851
03852 link = _dbus_connection_pop_message_link_unlocked (connection);
03853
03854 if (link != NULL)
03855 {
03856 DBusMessage *message;
03857
03858 message = link->data;
03859
03860 _dbus_list_free_link (link);
03861
03862 return message;
03863 }
03864 else
03865 return NULL;
03866 }
03867
03868 static void
03869 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03870 DBusList *message_link)
03871 {
03872 HAVE_LOCK_CHECK (connection);
03873
03874 _dbus_assert (message_link != NULL);
03875
03876 _dbus_assert (connection->message_borrowed == NULL);
03877
03878 _dbus_assert (connection->dispatch_acquired);
03879
03880 _dbus_list_prepend_link (&connection->incoming_messages,
03881 message_link);
03882 connection->n_incoming += 1;
03883
03884 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03885 message_link->data,
03886 dbus_message_get_type (message_link->data),
03887 dbus_message_get_interface (message_link->data) ?
03888 dbus_message_get_interface (message_link->data) :
03889 "no interface",
03890 dbus_message_get_member (message_link->data) ?
03891 dbus_message_get_member (message_link->data) :
03892 "no member",
03893 dbus_message_get_signature (message_link->data),
03894 connection, connection->n_incoming);
03895 }
03896
03916 DBusMessage*
03917 dbus_connection_pop_message (DBusConnection *connection)
03918 {
03919 DBusMessage *message;
03920 DBusDispatchStatus status;
03921
03922 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03923
03924
03925
03926
03927 status = dbus_connection_get_dispatch_status (connection);
03928 if (status != DBUS_DISPATCH_DATA_REMAINS)
03929 return NULL;
03930
03931 CONNECTION_LOCK (connection);
03932 _dbus_connection_acquire_dispatch (connection);
03933 HAVE_LOCK_CHECK (connection);
03934
03935 message = _dbus_connection_pop_message_unlocked (connection);
03936
03937 _dbus_verbose ("Returning popped message %p\n", message);
03938
03939 _dbus_connection_release_dispatch (connection);
03940
03941 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03942 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03943
03944 return message;
03945 }
03946
03954 static void
03955 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03956 {
03957 HAVE_LOCK_CHECK (connection);
03958
03959 _dbus_connection_ref_unlocked (connection);
03960 CONNECTION_UNLOCK (connection);
03961
03962 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03963 _dbus_mutex_lock (connection->dispatch_mutex);
03964
03965 while (connection->dispatch_acquired)
03966 {
03967 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03968 _dbus_condvar_wait (connection->dispatch_cond,
03969 connection->dispatch_mutex);
03970 }
03971
03972 _dbus_assert (!connection->dispatch_acquired);
03973
03974 connection->dispatch_acquired = TRUE;
03975
03976 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03977 _dbus_mutex_unlock (connection->dispatch_mutex);
03978
03979 CONNECTION_LOCK (connection);
03980 _dbus_connection_unref_unlocked (connection);
03981 }
03982
03990 static void
03991 _dbus_connection_release_dispatch (DBusConnection *connection)
03992 {
03993 HAVE_LOCK_CHECK (connection);
03994
03995 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03996 _dbus_mutex_lock (connection->dispatch_mutex);
03997
03998 _dbus_assert (connection->dispatch_acquired);
03999
04000 connection->dispatch_acquired = FALSE;
04001 _dbus_condvar_wake_one (connection->dispatch_cond);
04002
04003 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
04004 _dbus_mutex_unlock (connection->dispatch_mutex);
04005 }
04006
04007 static void
04008 _dbus_connection_failed_pop (DBusConnection *connection,
04009 DBusList *message_link)
04010 {
04011 _dbus_list_prepend_link (&connection->incoming_messages,
04012 message_link);
04013 connection->n_incoming += 1;
04014 }
04015
04016
04017 static void
04018 notify_disconnected_unlocked (DBusConnection *connection)
04019 {
04020 HAVE_LOCK_CHECK (connection);
04021
04022
04023
04024
04025
04026
04027
04028 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04029
04030
04031
04032
04033
04034 if (connection->n_outgoing > 0)
04035 {
04036 DBusList *link;
04037
04038 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04039 connection->n_outgoing);
04040
04041 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04042 {
04043 _dbus_connection_message_sent (connection, link->data);
04044 }
04045 }
04046 }
04047
04048
04049 static DBusDispatchStatus
04050 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04051 {
04052 HAVE_LOCK_CHECK (connection);
04053
04054 if (connection->disconnect_message_link != NULL)
04055 {
04056 _dbus_verbose ("Sending disconnect message from %s\n",
04057 _DBUS_FUNCTION_NAME);
04058
04059
04060
04061
04062 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04063
04064
04065
04066
04067 _dbus_connection_queue_synthesized_message_link (connection,
04068 connection->disconnect_message_link);
04069 connection->disconnect_message_link = NULL;
04070
04071 return DBUS_DISPATCH_DATA_REMAINS;
04072 }
04073
04074 return DBUS_DISPATCH_COMPLETE;
04075 }
04076
04077 static DBusDispatchStatus
04078 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04079 {
04080 HAVE_LOCK_CHECK (connection);
04081
04082 if (connection->n_incoming > 0)
04083 return DBUS_DISPATCH_DATA_REMAINS;
04084 else if (!_dbus_transport_queue_messages (connection->transport))
04085 return DBUS_DISPATCH_NEED_MEMORY;
04086 else
04087 {
04088 DBusDispatchStatus status;
04089 dbus_bool_t is_connected;
04090
04091 status = _dbus_transport_get_dispatch_status (connection->transport);
04092 is_connected = _dbus_transport_get_is_connected (connection->transport);
04093
04094 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04095 DISPATCH_STATUS_NAME (status), is_connected);
04096
04097 if (!is_connected)
04098 {
04099
04100
04101
04102
04103
04104
04105 notify_disconnected_unlocked (connection);
04106
04107
04108
04109
04110
04111
04112 if (status == DBUS_DISPATCH_COMPLETE)
04113 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04114 }
04115
04116 if (status != DBUS_DISPATCH_COMPLETE)
04117 return status;
04118 else if (connection->n_incoming > 0)
04119 return DBUS_DISPATCH_DATA_REMAINS;
04120 else
04121 return DBUS_DISPATCH_COMPLETE;
04122 }
04123 }
04124
04125 static void
04126 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04127 DBusDispatchStatus new_status)
04128 {
04129 dbus_bool_t changed;
04130 DBusDispatchStatusFunction function;
04131 void *data;
04132
04133 HAVE_LOCK_CHECK (connection);
04134
04135 _dbus_connection_ref_unlocked (connection);
04136
04137 changed = new_status != connection->last_dispatch_status;
04138
04139 connection->last_dispatch_status = new_status;
04140
04141 function = connection->dispatch_status_function;
04142 data = connection->dispatch_status_data;
04143
04144 if (connection->disconnected_message_arrived &&
04145 !connection->disconnected_message_processed)
04146 {
04147 connection->disconnected_message_processed = TRUE;
04148
04149
04150
04151
04152
04153 connection_forget_shared_unlocked (connection);
04154
04155 if (connection->exit_on_disconnect)
04156 {
04157 CONNECTION_UNLOCK (connection);
04158
04159 _dbus_verbose ("Exiting on Disconnected signal\n");
04160 _dbus_exit (1);
04161 _dbus_assert_not_reached ("Call to exit() returned");
04162 }
04163 }
04164
04165
04166 CONNECTION_UNLOCK (connection);
04167
04168 if (changed && function)
04169 {
04170 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04171 connection, new_status,
04172 DISPATCH_STATUS_NAME (new_status));
04173 (* function) (connection, new_status, data);
04174 }
04175
04176 dbus_connection_unref (connection);
04177 }
04178
04204 DBusDispatchStatus
04205 dbus_connection_get_dispatch_status (DBusConnection *connection)
04206 {
04207 DBusDispatchStatus status;
04208
04209 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04210
04211 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04212
04213 CONNECTION_LOCK (connection);
04214
04215 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04216
04217 CONNECTION_UNLOCK (connection);
04218
04219 return status;
04220 }
04221
04225 static DBusHandlerResult
04226 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04227 DBusMessage *message)
04228 {
04229 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04230 {
04231
04232 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04233 }
04234 else if (dbus_message_is_method_call (message,
04235 DBUS_INTERFACE_PEER,
04236 "Ping"))
04237 {
04238 DBusMessage *ret;
04239 dbus_bool_t sent;
04240
04241 ret = dbus_message_new_method_return (message);
04242 if (ret == NULL)
04243 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04244
04245 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04246
04247 dbus_message_unref (ret);
04248
04249 if (!sent)
04250 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04251
04252 return DBUS_HANDLER_RESULT_HANDLED;
04253 }
04254 else if (dbus_message_is_method_call (message,
04255 DBUS_INTERFACE_PEER,
04256 "GetMachineId"))
04257 {
04258 DBusMessage *ret;
04259 dbus_bool_t sent;
04260 DBusString uuid;
04261
04262 ret = dbus_message_new_method_return (message);
04263 if (ret == NULL)
04264 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04265
04266 sent = FALSE;
04267 _dbus_string_init (&uuid);
04268 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04269 {
04270 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04271 if (dbus_message_append_args (ret,
04272 DBUS_TYPE_STRING, &v_STRING,
04273 DBUS_TYPE_INVALID))
04274 {
04275 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04276 }
04277 }
04278 _dbus_string_free (&uuid);
04279
04280 dbus_message_unref (ret);
04281
04282 if (!sent)
04283 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04284
04285 return DBUS_HANDLER_RESULT_HANDLED;
04286 }
04287 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04288 {
04289
04290
04291
04292
04293
04294 DBusMessage *ret;
04295 dbus_bool_t sent;
04296
04297 ret = dbus_message_new_error (message,
04298 DBUS_ERROR_UNKNOWN_METHOD,
04299 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04300 if (ret == NULL)
04301 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04302
04303 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04304
04305 dbus_message_unref (ret);
04306
04307 if (!sent)
04308 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04309
04310 return DBUS_HANDLER_RESULT_HANDLED;
04311 }
04312 else
04313 {
04314 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04315 }
04316 }
04317
04324 static DBusHandlerResult
04325 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04326 DBusMessage *message)
04327 {
04328
04329
04330
04331 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04332 }
04333
04376 DBusDispatchStatus
04377 dbus_connection_dispatch (DBusConnection *connection)
04378 {
04379 DBusMessage *message;
04380 DBusList *link, *filter_list_copy, *message_link;
04381 DBusHandlerResult result;
04382 DBusPendingCall *pending;
04383 dbus_int32_t reply_serial;
04384 DBusDispatchStatus status;
04385
04386 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04387
04388 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04389
04390 CONNECTION_LOCK (connection);
04391 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04392 if (status != DBUS_DISPATCH_DATA_REMAINS)
04393 {
04394
04395 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04396 return status;
04397 }
04398
04399
04400
04401
04402 _dbus_connection_ref_unlocked (connection);
04403
04404 _dbus_connection_acquire_dispatch (connection);
04405 HAVE_LOCK_CHECK (connection);
04406
04407 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04408 if (message_link == NULL)
04409 {
04410
04411
04412 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04413
04414 _dbus_connection_release_dispatch (connection);
04415
04416 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04417
04418 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04419
04420 dbus_connection_unref (connection);
04421
04422 return status;
04423 }
04424
04425 message = message_link->data;
04426
04427 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04428 message,
04429 dbus_message_get_type (message),
04430 dbus_message_get_interface (message) ?
04431 dbus_message_get_interface (message) :
04432 "no interface",
04433 dbus_message_get_member (message) ?
04434 dbus_message_get_member (message) :
04435 "no member",
04436 dbus_message_get_signature (message));
04437
04438 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04439
04440
04441
04442
04443
04444
04445
04446
04447 reply_serial = dbus_message_get_reply_serial (message);
04448 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04449 reply_serial);
04450 if (pending)
04451 {
04452 _dbus_verbose ("Dispatching a pending reply\n");
04453 complete_pending_call_and_unlock (connection, pending, message);
04454 pending = NULL;
04455
04456 CONNECTION_LOCK (connection);
04457 _dbus_verbose ("pending call completed in dispatch\n");
04458 result = DBUS_HANDLER_RESULT_HANDLED;
04459 goto out;
04460 }
04461
04462 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04463 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04464 goto out;
04465
04466 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04467 {
04468 _dbus_connection_release_dispatch (connection);
04469 HAVE_LOCK_CHECK (connection);
04470
04471 _dbus_connection_failed_pop (connection, message_link);
04472
04473
04474 _dbus_connection_update_dispatch_status_and_unlock (connection,
04475 DBUS_DISPATCH_NEED_MEMORY);
04476
04477 if (pending)
04478 dbus_pending_call_unref (pending);
04479 dbus_connection_unref (connection);
04480
04481 return DBUS_DISPATCH_NEED_MEMORY;
04482 }
04483
04484 _dbus_list_foreach (&filter_list_copy,
04485 (DBusForeachFunction)_dbus_message_filter_ref,
04486 NULL);
04487
04488
04489
04490
04491 CONNECTION_UNLOCK (connection);
04492
04493 link = _dbus_list_get_first_link (&filter_list_copy);
04494 while (link != NULL)
04495 {
04496 DBusMessageFilter *filter = link->data;
04497 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04498
04499 if (filter->function == NULL)
04500 {
04501 _dbus_verbose (" filter was removed in a callback function\n");
04502 link = next;
04503 continue;
04504 }
04505
04506 _dbus_verbose (" running filter on message %p\n", message);
04507 result = (* filter->function) (connection, message, filter->user_data);
04508
04509 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04510 break;
04511
04512 link = next;
04513 }
04514
04515 _dbus_list_foreach (&filter_list_copy,
04516 (DBusForeachFunction)_dbus_message_filter_unref,
04517 NULL);
04518 _dbus_list_clear (&filter_list_copy);
04519
04520 CONNECTION_LOCK (connection);
04521
04522 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04523 {
04524 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04525 goto out;
04526 }
04527 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04528 {
04529 _dbus_verbose ("filter handled message in dispatch\n");
04530 goto out;
04531 }
04532
04533
04534
04535
04536 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
04537 message,
04538 dbus_message_get_type (message),
04539 dbus_message_get_interface (message) ?
04540 dbus_message_get_interface (message) :
04541 "no interface",
04542 dbus_message_get_member (message) ?
04543 dbus_message_get_member (message) :
04544 "no member",
04545 dbus_message_get_signature (message));
04546
04547 HAVE_LOCK_CHECK (connection);
04548 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04549 message);
04550
04551 CONNECTION_LOCK (connection);
04552
04553 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04554 {
04555 _dbus_verbose ("object tree handled message in dispatch\n");
04556 goto out;
04557 }
04558
04559 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04560 {
04561 DBusMessage *reply;
04562 DBusString str;
04563 DBusPreallocatedSend *preallocated;
04564
04565 _dbus_verbose (" sending error %s\n",
04566 DBUS_ERROR_UNKNOWN_METHOD);
04567
04568 if (!_dbus_string_init (&str))
04569 {
04570 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04571 _dbus_verbose ("no memory for error string in dispatch\n");
04572 goto out;
04573 }
04574
04575 if (!_dbus_string_append_printf (&str,
04576 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04577 dbus_message_get_member (message),
04578 dbus_message_get_signature (message),
04579 dbus_message_get_interface (message)))
04580 {
04581 _dbus_string_free (&str);
04582 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04583 _dbus_verbose ("no memory for error string in dispatch\n");
04584 goto out;
04585 }
04586
04587 reply = dbus_message_new_error (message,
04588 DBUS_ERROR_UNKNOWN_METHOD,
04589 _dbus_string_get_const_data (&str));
04590 _dbus_string_free (&str);
04591
04592 if (reply == NULL)
04593 {
04594 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04595 _dbus_verbose ("no memory for error reply in dispatch\n");
04596 goto out;
04597 }
04598
04599 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04600
04601 if (preallocated == NULL)
04602 {
04603 dbus_message_unref (reply);
04604 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04605 _dbus_verbose ("no memory for error send in dispatch\n");
04606 goto out;
04607 }
04608
04609 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04610 reply, NULL);
04611
04612 dbus_message_unref (reply);
04613
04614 result = DBUS_HANDLER_RESULT_HANDLED;
04615 }
04616
04617 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04618 dbus_message_get_type (message),
04619 dbus_message_get_interface (message) ?
04620 dbus_message_get_interface (message) :
04621 "no interface",
04622 dbus_message_get_member (message) ?
04623 dbus_message_get_member (message) :
04624 "no member",
04625 dbus_message_get_signature (message),
04626 connection);
04627
04628 out:
04629 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04630 {
04631 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04632
04633
04634
04635
04636
04637 _dbus_connection_putback_message_link_unlocked (connection,
04638 message_link);
04639 }
04640 else
04641 {
04642 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04643
04644 _dbus_list_free_link (message_link);
04645 dbus_message_unref (message);
04646
04647
04648 }
04649
04650 _dbus_connection_release_dispatch (connection);
04651 HAVE_LOCK_CHECK (connection);
04652
04653 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04654 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04655
04656
04657 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04658
04659 dbus_connection_unref (connection);
04660
04661 return status;
04662 }
04663
04723 dbus_bool_t
04724 dbus_connection_set_watch_functions (DBusConnection *connection,
04725 DBusAddWatchFunction add_function,
04726 DBusRemoveWatchFunction remove_function,
04727 DBusWatchToggledFunction toggled_function,
04728 void *data,
04729 DBusFreeFunction free_data_function)
04730 {
04731 dbus_bool_t retval;
04732 DBusWatchList *watches;
04733
04734 _dbus_return_val_if_fail (connection != NULL, FALSE);
04735
04736 CONNECTION_LOCK (connection);
04737
04738 #ifndef DBUS_DISABLE_CHECKS
04739 if (connection->watches == NULL)
04740 {
04741 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04742 _DBUS_FUNCTION_NAME);
04743 return FALSE;
04744 }
04745 #endif
04746
04747
04748 _dbus_connection_ref_unlocked (connection);
04749
04750
04751
04752
04753
04754 watches = connection->watches;
04755 connection->watches = NULL;
04756 CONNECTION_UNLOCK (connection);
04757
04758 retval = _dbus_watch_list_set_functions (watches,
04759 add_function, remove_function,
04760 toggled_function,
04761 data, free_data_function);
04762 CONNECTION_LOCK (connection);
04763 connection->watches = watches;
04764
04765 CONNECTION_UNLOCK (connection);
04766
04767 dbus_connection_unref (connection);
04768
04769 return retval;
04770 }
04771
04805 dbus_bool_t
04806 dbus_connection_set_timeout_functions (DBusConnection *connection,
04807 DBusAddTimeoutFunction add_function,
04808 DBusRemoveTimeoutFunction remove_function,
04809 DBusTimeoutToggledFunction toggled_function,
04810 void *data,
04811 DBusFreeFunction free_data_function)
04812 {
04813 dbus_bool_t retval;
04814 DBusTimeoutList *timeouts;
04815
04816 _dbus_return_val_if_fail (connection != NULL, FALSE);
04817
04818 CONNECTION_LOCK (connection);
04819
04820 #ifndef DBUS_DISABLE_CHECKS
04821 if (connection->timeouts == NULL)
04822 {
04823 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04824 _DBUS_FUNCTION_NAME);
04825 return FALSE;
04826 }
04827 #endif
04828
04829
04830 _dbus_connection_ref_unlocked (connection);
04831
04832 timeouts = connection->timeouts;
04833 connection->timeouts = NULL;
04834 CONNECTION_UNLOCK (connection);
04835
04836 retval = _dbus_timeout_list_set_functions (timeouts,
04837 add_function, remove_function,
04838 toggled_function,
04839 data, free_data_function);
04840 CONNECTION_LOCK (connection);
04841 connection->timeouts = timeouts;
04842
04843 CONNECTION_UNLOCK (connection);
04844
04845 dbus_connection_unref (connection);
04846
04847 return retval;
04848 }
04849
04864 void
04865 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04866 DBusWakeupMainFunction wakeup_main_function,
04867 void *data,
04868 DBusFreeFunction free_data_function)
04869 {
04870 void *old_data;
04871 DBusFreeFunction old_free_data;
04872
04873 _dbus_return_if_fail (connection != NULL);
04874
04875 CONNECTION_LOCK (connection);
04876 old_data = connection->wakeup_main_data;
04877 old_free_data = connection->free_wakeup_main_data;
04878
04879 connection->wakeup_main_function = wakeup_main_function;
04880 connection->wakeup_main_data = data;
04881 connection->free_wakeup_main_data = free_data_function;
04882
04883 CONNECTION_UNLOCK (connection);
04884
04885
04886 if (old_free_data)
04887 (*old_free_data) (old_data);
04888 }
04889
04910 void
04911 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04912 DBusDispatchStatusFunction function,
04913 void *data,
04914 DBusFreeFunction free_data_function)
04915 {
04916 void *old_data;
04917 DBusFreeFunction old_free_data;
04918
04919 _dbus_return_if_fail (connection != NULL);
04920
04921 CONNECTION_LOCK (connection);
04922 old_data = connection->dispatch_status_data;
04923 old_free_data = connection->free_dispatch_status_data;
04924
04925 connection->dispatch_status_function = function;
04926 connection->dispatch_status_data = data;
04927 connection->free_dispatch_status_data = free_data_function;
04928
04929 CONNECTION_UNLOCK (connection);
04930
04931
04932 if (old_free_data)
04933 (*old_free_data) (old_data);
04934 }
04935
04955 dbus_bool_t
04956 dbus_connection_get_unix_fd (DBusConnection *connection,
04957 int *fd)
04958 {
04959 _dbus_return_val_if_fail (connection != NULL, FALSE);
04960 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04961
04962 #ifdef DBUS_WIN
04963
04964 return FALSE;
04965 #endif
04966
04967 return dbus_connection_get_socket(connection, fd);
04968 }
04969
04985 dbus_bool_t
04986 dbus_connection_get_socket(DBusConnection *connection,
04987 int *fd)
04988 {
04989 dbus_bool_t retval;
04990
04991 _dbus_return_val_if_fail (connection != NULL, FALSE);
04992 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04993
04994 CONNECTION_LOCK (connection);
04995
04996 retval = _dbus_transport_get_socket_fd (connection->transport,
04997 fd);
04998
04999 CONNECTION_UNLOCK (connection);
05000
05001 return retval;
05002 }
05003
05004
05027 dbus_bool_t
05028 dbus_connection_get_unix_user (DBusConnection *connection,
05029 unsigned long *uid)
05030 {
05031 dbus_bool_t result;
05032
05033 _dbus_return_val_if_fail (connection != NULL, FALSE);
05034 _dbus_return_val_if_fail (uid != NULL, FALSE);
05035
05036 CONNECTION_LOCK (connection);
05037
05038 if (!_dbus_transport_get_is_authenticated (connection->transport))
05039 result = FALSE;
05040 else
05041 result = _dbus_transport_get_unix_user (connection->transport,
05042 uid);
05043
05044 #ifdef DBUS_WIN
05045 _dbus_assert (!result);
05046 #endif
05047
05048 CONNECTION_UNLOCK (connection);
05049
05050 return result;
05051 }
05052
05063 dbus_bool_t
05064 dbus_connection_get_unix_process_id (DBusConnection *connection,
05065 unsigned long *pid)
05066 {
05067 dbus_bool_t result;
05068
05069 _dbus_return_val_if_fail (connection != NULL, FALSE);
05070 _dbus_return_val_if_fail (pid != NULL, FALSE);
05071
05072 CONNECTION_LOCK (connection);
05073
05074 if (!_dbus_transport_get_is_authenticated (connection->transport))
05075 result = FALSE;
05076 else
05077 result = _dbus_transport_get_unix_process_id (connection->transport,
05078 pid);
05079 #ifdef DBUS_WIN
05080 _dbus_assert (!result);
05081 #endif
05082
05083 CONNECTION_UNLOCK (connection);
05084
05085 return result;
05086 }
05087
05098 dbus_bool_t
05099 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05100 void **data,
05101 dbus_int32_t *data_size)
05102 {
05103 dbus_bool_t result;
05104
05105 _dbus_return_val_if_fail (connection != NULL, FALSE);
05106 _dbus_return_val_if_fail (data != NULL, FALSE);
05107 _dbus_return_val_if_fail (data_size != NULL, FALSE);
05108
05109 CONNECTION_LOCK (connection);
05110
05111 if (!_dbus_transport_get_is_authenticated (connection->transport))
05112 result = FALSE;
05113 else
05114 result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05115 data,
05116 data_size);
05117 CONNECTION_UNLOCK (connection);
05118
05119 return result;
05120 }
05121
05144 void
05145 dbus_connection_set_unix_user_function (DBusConnection *connection,
05146 DBusAllowUnixUserFunction function,
05147 void *data,
05148 DBusFreeFunction free_data_function)
05149 {
05150 void *old_data = NULL;
05151 DBusFreeFunction old_free_function = NULL;
05152
05153 _dbus_return_if_fail (connection != NULL);
05154
05155 CONNECTION_LOCK (connection);
05156 _dbus_transport_set_unix_user_function (connection->transport,
05157 function, data, free_data_function,
05158 &old_data, &old_free_function);
05159 CONNECTION_UNLOCK (connection);
05160
05161 if (old_free_function != NULL)
05162 (* old_free_function) (old_data);
05163 }
05164
05196 dbus_bool_t
05197 dbus_connection_get_windows_user (DBusConnection *connection,
05198 char **windows_sid_p)
05199 {
05200 dbus_bool_t result;
05201
05202 _dbus_return_val_if_fail (connection != NULL, FALSE);
05203 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05204
05205 CONNECTION_LOCK (connection);
05206
05207 if (!_dbus_transport_get_is_authenticated (connection->transport))
05208 result = FALSE;
05209 else
05210 result = _dbus_transport_get_windows_user (connection->transport,
05211 windows_sid_p);
05212
05213 #ifdef DBUS_UNIX
05214 _dbus_assert (!result);
05215 #endif
05216
05217 CONNECTION_UNLOCK (connection);
05218
05219 return result;
05220 }
05221
05243 void
05244 dbus_connection_set_windows_user_function (DBusConnection *connection,
05245 DBusAllowWindowsUserFunction function,
05246 void *data,
05247 DBusFreeFunction free_data_function)
05248 {
05249 void *old_data = NULL;
05250 DBusFreeFunction old_free_function = NULL;
05251
05252 _dbus_return_if_fail (connection != NULL);
05253
05254 CONNECTION_LOCK (connection);
05255 _dbus_transport_set_windows_user_function (connection->transport,
05256 function, data, free_data_function,
05257 &old_data, &old_free_function);
05258 CONNECTION_UNLOCK (connection);
05259
05260 if (old_free_function != NULL)
05261 (* old_free_function) (old_data);
05262 }
05263
05290 void
05291 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05292 dbus_bool_t value)
05293 {
05294 _dbus_return_if_fail (connection != NULL);
05295
05296 CONNECTION_LOCK (connection);
05297 _dbus_transport_set_allow_anonymous (connection->transport, value);
05298 CONNECTION_UNLOCK (connection);
05299 }
05300
05318 void
05319 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05320 dbus_bool_t value)
05321 {
05322 _dbus_return_if_fail (connection != NULL);
05323
05324 CONNECTION_LOCK (connection);
05325 connection->route_peer_messages = TRUE;
05326 CONNECTION_UNLOCK (connection);
05327 }
05328
05350 dbus_bool_t
05351 dbus_connection_add_filter (DBusConnection *connection,
05352 DBusHandleMessageFunction function,
05353 void *user_data,
05354 DBusFreeFunction free_data_function)
05355 {
05356 DBusMessageFilter *filter;
05357
05358 _dbus_return_val_if_fail (connection != NULL, FALSE);
05359 _dbus_return_val_if_fail (function != NULL, FALSE);
05360
05361 filter = dbus_new0 (DBusMessageFilter, 1);
05362 if (filter == NULL)
05363 return FALSE;
05364
05365 filter->refcount.value = 1;
05366
05367 CONNECTION_LOCK (connection);
05368
05369 if (!_dbus_list_append (&connection->filter_list,
05370 filter))
05371 {
05372 _dbus_message_filter_unref (filter);
05373 CONNECTION_UNLOCK (connection);
05374 return FALSE;
05375 }
05376
05377
05378
05379
05380
05381
05382 filter->function = function;
05383 filter->user_data = user_data;
05384 filter->free_user_data_function = free_data_function;
05385
05386 CONNECTION_UNLOCK (connection);
05387 return TRUE;
05388 }
05389
05402 void
05403 dbus_connection_remove_filter (DBusConnection *connection,
05404 DBusHandleMessageFunction function,
05405 void *user_data)
05406 {
05407 DBusList *link;
05408 DBusMessageFilter *filter;
05409
05410 _dbus_return_if_fail (connection != NULL);
05411 _dbus_return_if_fail (function != NULL);
05412
05413 CONNECTION_LOCK (connection);
05414
05415 filter = NULL;
05416
05417 link = _dbus_list_get_last_link (&connection->filter_list);
05418 while (link != NULL)
05419 {
05420 filter = link->data;
05421
05422 if (filter->function == function &&
05423 filter->user_data == user_data)
05424 {
05425 _dbus_list_remove_link (&connection->filter_list, link);
05426 filter->function = NULL;
05427
05428 break;
05429 }
05430
05431 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05432 filter = NULL;
05433 }
05434
05435 CONNECTION_UNLOCK (connection);
05436
05437 #ifndef DBUS_DISABLE_CHECKS
05438 if (filter == NULL)
05439 {
05440 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05441 function, user_data);
05442 return;
05443 }
05444 #endif
05445
05446
05447 if (filter->free_user_data_function)
05448 (* filter->free_user_data_function) (filter->user_data);
05449
05450 filter->free_user_data_function = NULL;
05451 filter->user_data = NULL;
05452
05453 _dbus_message_filter_unref (filter);
05454 }
05455
05468 dbus_bool_t
05469 dbus_connection_try_register_object_path (DBusConnection *connection,
05470 const char *path,
05471 const DBusObjectPathVTable *vtable,
05472 void *user_data,
05473 DBusError *error)
05474 {
05475 char **decomposed_path;
05476 dbus_bool_t retval;
05477
05478 _dbus_return_val_if_fail (connection != NULL, FALSE);
05479 _dbus_return_val_if_fail (path != NULL, FALSE);
05480 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05481 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05482
05483 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05484 return FALSE;
05485
05486 CONNECTION_LOCK (connection);
05487
05488 retval = _dbus_object_tree_register (connection->objects,
05489 FALSE,
05490 (const char **) decomposed_path, vtable,
05491 user_data, error);
05492
05493 CONNECTION_UNLOCK (connection);
05494
05495 dbus_free_string_array (decomposed_path);
05496
05497 return retval;
05498 }
05499
05514 dbus_bool_t
05515 dbus_connection_register_object_path (DBusConnection *connection,
05516 const char *path,
05517 const DBusObjectPathVTable *vtable,
05518 void *user_data)
05519 {
05520 char **decomposed_path;
05521 dbus_bool_t retval;
05522 DBusError error = DBUS_ERROR_INIT;
05523
05524 _dbus_return_val_if_fail (connection != NULL, FALSE);
05525 _dbus_return_val_if_fail (path != NULL, FALSE);
05526 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05527 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05528
05529 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05530 return FALSE;
05531
05532 CONNECTION_LOCK (connection);
05533
05534 retval = _dbus_object_tree_register (connection->objects,
05535 FALSE,
05536 (const char **) decomposed_path, vtable,
05537 user_data, &error);
05538
05539 CONNECTION_UNLOCK (connection);
05540
05541 dbus_free_string_array (decomposed_path);
05542
05543 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05544 {
05545 _dbus_warn ("%s\n", error.message);
05546 dbus_error_free (&error);
05547 return FALSE;
05548 }
05549
05550 return retval;
05551 }
05552
05567 dbus_bool_t
05568 dbus_connection_try_register_fallback (DBusConnection *connection,
05569 const char *path,
05570 const DBusObjectPathVTable *vtable,
05571 void *user_data,
05572 DBusError *error)
05573 {
05574 char **decomposed_path;
05575 dbus_bool_t retval;
05576
05577 _dbus_return_val_if_fail (connection != NULL, FALSE);
05578 _dbus_return_val_if_fail (path != NULL, FALSE);
05579 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05580 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05581
05582 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05583 return FALSE;
05584
05585 CONNECTION_LOCK (connection);
05586
05587 retval = _dbus_object_tree_register (connection->objects,
05588 TRUE,
05589 (const char **) decomposed_path, vtable,
05590 user_data, error);
05591
05592 CONNECTION_UNLOCK (connection);
05593
05594 dbus_free_string_array (decomposed_path);
05595
05596 return retval;
05597 }
05598
05615 dbus_bool_t
05616 dbus_connection_register_fallback (DBusConnection *connection,
05617 const char *path,
05618 const DBusObjectPathVTable *vtable,
05619 void *user_data)
05620 {
05621 char **decomposed_path;
05622 dbus_bool_t retval;
05623 DBusError error = DBUS_ERROR_INIT;
05624
05625 _dbus_return_val_if_fail (connection != NULL, FALSE);
05626 _dbus_return_val_if_fail (path != NULL, FALSE);
05627 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05628 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05629
05630 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05631 return FALSE;
05632
05633 CONNECTION_LOCK (connection);
05634
05635 retval = _dbus_object_tree_register (connection->objects,
05636 TRUE,
05637 (const char **) decomposed_path, vtable,
05638 user_data, &error);
05639
05640 CONNECTION_UNLOCK (connection);
05641
05642 dbus_free_string_array (decomposed_path);
05643
05644 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05645 {
05646 _dbus_warn ("%s\n", error.message);
05647 dbus_error_free (&error);
05648 return FALSE;
05649 }
05650
05651 return retval;
05652 }
05653
05663 dbus_bool_t
05664 dbus_connection_unregister_object_path (DBusConnection *connection,
05665 const char *path)
05666 {
05667 char **decomposed_path;
05668
05669 _dbus_return_val_if_fail (connection != NULL, FALSE);
05670 _dbus_return_val_if_fail (path != NULL, FALSE);
05671 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05672
05673 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05674 return FALSE;
05675
05676 CONNECTION_LOCK (connection);
05677
05678 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05679
05680 dbus_free_string_array (decomposed_path);
05681
05682 return TRUE;
05683 }
05684
05695 dbus_bool_t
05696 dbus_connection_get_object_path_data (DBusConnection *connection,
05697 const char *path,
05698 void **data_p)
05699 {
05700 char **decomposed_path;
05701
05702 _dbus_return_val_if_fail (connection != NULL, FALSE);
05703 _dbus_return_val_if_fail (path != NULL, FALSE);
05704 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05705
05706 *data_p = NULL;
05707
05708 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05709 return FALSE;
05710
05711 CONNECTION_LOCK (connection);
05712
05713 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05714
05715 CONNECTION_UNLOCK (connection);
05716
05717 dbus_free_string_array (decomposed_path);
05718
05719 return TRUE;
05720 }
05721
05732 dbus_bool_t
05733 dbus_connection_list_registered (DBusConnection *connection,
05734 const char *parent_path,
05735 char ***child_entries)
05736 {
05737 char **decomposed_path;
05738 dbus_bool_t retval;
05739 _dbus_return_val_if_fail (connection != NULL, FALSE);
05740 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05741 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05742 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05743
05744 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05745 return FALSE;
05746
05747 CONNECTION_LOCK (connection);
05748
05749 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05750 (const char **) decomposed_path,
05751 child_entries);
05752 dbus_free_string_array (decomposed_path);
05753
05754 return retval;
05755 }
05756
05757 static DBusDataSlotAllocator slot_allocator;
05758 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05759
05774 dbus_bool_t
05775 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05776 {
05777 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05778 &_DBUS_LOCK_NAME (connection_slots),
05779 slot_p);
05780 }
05781
05793 void
05794 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05795 {
05796 _dbus_return_if_fail (*slot_p >= 0);
05797
05798 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05799 }
05800
05814 dbus_bool_t
05815 dbus_connection_set_data (DBusConnection *connection,
05816 dbus_int32_t slot,
05817 void *data,
05818 DBusFreeFunction free_data_func)
05819 {
05820 DBusFreeFunction old_free_func;
05821 void *old_data;
05822 dbus_bool_t retval;
05823
05824 _dbus_return_val_if_fail (connection != NULL, FALSE);
05825 _dbus_return_val_if_fail (slot >= 0, FALSE);
05826
05827 CONNECTION_LOCK (connection);
05828
05829 retval = _dbus_data_slot_list_set (&slot_allocator,
05830 &connection->slot_list,
05831 slot, data, free_data_func,
05832 &old_free_func, &old_data);
05833
05834 CONNECTION_UNLOCK (connection);
05835
05836 if (retval)
05837 {
05838
05839 if (old_free_func)
05840 (* old_free_func) (old_data);
05841 }
05842
05843 return retval;
05844 }
05845
05854 void*
05855 dbus_connection_get_data (DBusConnection *connection,
05856 dbus_int32_t slot)
05857 {
05858 void *res;
05859
05860 _dbus_return_val_if_fail (connection != NULL, NULL);
05861
05862 CONNECTION_LOCK (connection);
05863
05864 res = _dbus_data_slot_list_get (&slot_allocator,
05865 &connection->slot_list,
05866 slot);
05867
05868 CONNECTION_UNLOCK (connection);
05869
05870 return res;
05871 }
05872
05879 void
05880 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05881 {
05882 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05883 }
05884
05893 void
05894 dbus_connection_set_max_message_size (DBusConnection *connection,
05895 long size)
05896 {
05897 _dbus_return_if_fail (connection != NULL);
05898
05899 CONNECTION_LOCK (connection);
05900 _dbus_transport_set_max_message_size (connection->transport,
05901 size);
05902 CONNECTION_UNLOCK (connection);
05903 }
05904
05911 long
05912 dbus_connection_get_max_message_size (DBusConnection *connection)
05913 {
05914 long res;
05915
05916 _dbus_return_val_if_fail (connection != NULL, 0);
05917
05918 CONNECTION_LOCK (connection);
05919 res = _dbus_transport_get_max_message_size (connection->transport);
05920 CONNECTION_UNLOCK (connection);
05921 return res;
05922 }
05923
05949 void
05950 dbus_connection_set_max_received_size (DBusConnection *connection,
05951 long size)
05952 {
05953 _dbus_return_if_fail (connection != NULL);
05954
05955 CONNECTION_LOCK (connection);
05956 _dbus_transport_set_max_received_size (connection->transport,
05957 size);
05958 CONNECTION_UNLOCK (connection);
05959 }
05960
05967 long
05968 dbus_connection_get_max_received_size (DBusConnection *connection)
05969 {
05970 long res;
05971
05972 _dbus_return_val_if_fail (connection != NULL, 0);
05973
05974 CONNECTION_LOCK (connection);
05975 res = _dbus_transport_get_max_received_size (connection->transport);
05976 CONNECTION_UNLOCK (connection);
05977 return res;
05978 }
05979
05990 long
05991 dbus_connection_get_outgoing_size (DBusConnection *connection)
05992 {
05993 long res;
05994
05995 _dbus_return_val_if_fail (connection != NULL, 0);
05996
05997 CONNECTION_LOCK (connection);
05998 res = _dbus_counter_get_value (connection->outgoing_counter);
05999 CONNECTION_UNLOCK (connection);
06000 return res;
06001 }
06002