00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "dbus-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-pending-call-internal.h"
00033 #include "dbus-list.h"
00034 #include "dbus-hash.h"
00035 #include "dbus-message-internal.h"
00036 #include "dbus-threads.h"
00037 #include "dbus-protocol.h"
00038 #include "dbus-dataslot.h"
00039 #include "dbus-string.h"
00040 #include "dbus-pending-call.h"
00041 #include "dbus-object-tree.h"
00042 #include "dbus-threads-internal.h"
00043 #include "dbus-bus.h"
00044
00045 #ifdef DBUS_DISABLE_CHECKS
00046 #define TOOK_LOCK_CHECK(connection)
00047 #define RELEASING_LOCK_CHECK(connection)
00048 #define HAVE_LOCK_CHECK(connection)
00049 #else
00050 #define TOOK_LOCK_CHECK(connection) do { \
00051 _dbus_assert (!(connection)->have_connection_lock); \
00052 (connection)->have_connection_lock = TRUE; \
00053 } while (0)
00054 #define RELEASING_LOCK_CHECK(connection) do { \
00055 _dbus_assert ((connection)->have_connection_lock); \
00056 (connection)->have_connection_lock = FALSE; \
00057 } while (0)
00058 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00059
00060 #endif
00061
00062 #define TRACE_LOCKS 1
00063
00064 #define CONNECTION_LOCK(connection) do { \
00065 if (TRACE_LOCKS) { _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00066 _dbus_mutex_lock ((connection)->mutex); \
00067 TOOK_LOCK_CHECK (connection); \
00068 } while (0)
00069
00070 #define CONNECTION_UNLOCK(connection) do { \
00071 if (TRACE_LOCKS) { _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00072 RELEASING_LOCK_CHECK (connection); \
00073 _dbus_mutex_unlock ((connection)->mutex); \
00074 } while (0)
00075
00076 #define DISPATCH_STATUS_NAME(s) \
00077 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00078 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00079 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00080 "???")
00081
00202 typedef struct DBusMessageFilter DBusMessageFilter;
00203
00207 struct DBusMessageFilter
00208 {
00209 DBusAtomic refcount;
00210 DBusHandleMessageFunction function;
00211 void *user_data;
00212 DBusFreeFunction free_user_data_function;
00213 };
00214
00215
00219 struct DBusPreallocatedSend
00220 {
00221 DBusConnection *connection;
00222 DBusList *queue_link;
00223 DBusList *counter_link;
00224 };
00225
00226 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00227
00231 struct DBusConnection
00232 {
00233 DBusAtomic refcount;
00235 DBusMutex *mutex;
00237 DBusMutex *dispatch_mutex;
00238 DBusCondVar *dispatch_cond;
00239 DBusMutex *io_path_mutex;
00240 DBusCondVar *io_path_cond;
00242 DBusList *outgoing_messages;
00243 DBusList *incoming_messages;
00245 DBusMessage *message_borrowed;
00249 int n_outgoing;
00250 int n_incoming;
00252 DBusCounter *outgoing_counter;
00254 DBusTransport *transport;
00255 DBusWatchList *watches;
00256 DBusTimeoutList *timeouts;
00258 DBusList *filter_list;
00260 DBusDataSlotList slot_list;
00262 DBusHashTable *pending_replies;
00264 dbus_uint32_t client_serial;
00265 DBusList *disconnect_message_link;
00267 DBusWakeupMainFunction wakeup_main_function;
00268 void *wakeup_main_data;
00269 DBusFreeFunction free_wakeup_main_data;
00271 DBusDispatchStatusFunction dispatch_status_function;
00272 void *dispatch_status_data;
00273 DBusFreeFunction free_dispatch_status_data;
00275 DBusDispatchStatus last_dispatch_status;
00277 DBusList *link_cache;
00280 DBusObjectTree *objects;
00282 char *server_guid;
00284
00285
00286
00287
00288 dbus_bool_t dispatch_acquired;
00289 dbus_bool_t io_path_acquired;
00291 unsigned int shareable : 1;
00293 unsigned int exit_on_disconnect : 1;
00295 unsigned int route_peer_messages : 1;
00297 unsigned int disconnected_message_arrived : 1;
00301 unsigned int disconnected_message_processed : 1;
00305 #ifndef DBUS_DISABLE_CHECKS
00306 unsigned int have_connection_lock : 1;
00307 #endif
00308
00309 #ifndef DBUS_DISABLE_CHECKS
00310 int generation;
00311 #endif
00312 };
00313
00314 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00315 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00316 DBusDispatchStatus new_status);
00317 static void _dbus_connection_last_unref (DBusConnection *connection);
00318 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00319 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00320 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00321 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
00322 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
00323
00324 static DBusMessageFilter *
00325 _dbus_message_filter_ref (DBusMessageFilter *filter)
00326 {
00327 _dbus_assert (filter->refcount.value > 0);
00328 _dbus_atomic_inc (&filter->refcount);
00329
00330 return filter;
00331 }
00332
00333 static void
00334 _dbus_message_filter_unref (DBusMessageFilter *filter)
00335 {
00336 _dbus_assert (filter->refcount.value > 0);
00337
00338 if (_dbus_atomic_dec (&filter->refcount) == 1)
00339 {
00340 if (filter->free_user_data_function)
00341 (* filter->free_user_data_function) (filter->user_data);
00342
00343 dbus_free (filter);
00344 }
00345 }
00346
00352 void
00353 _dbus_connection_lock (DBusConnection *connection)
00354 {
00355 CONNECTION_LOCK (connection);
00356 }
00357
00363 void
00364 _dbus_connection_unlock (DBusConnection *connection)
00365 {
00366 CONNECTION_UNLOCK (connection);
00367 }
00368
00376 static void
00377 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00378 {
00379 if (connection->wakeup_main_function)
00380 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00381 }
00382
00383 #ifdef DBUS_BUILD_TESTS
00384
00394 dbus_bool_t
00395 _dbus_connection_queue_received_message (DBusConnection *connection,
00396 DBusMessage *message)
00397 {
00398 DBusList *link;
00399
00400 link = _dbus_list_alloc_link (message);
00401 if (link == NULL)
00402 return FALSE;
00403
00404 dbus_message_ref (message);
00405 _dbus_connection_queue_received_message_link (connection, link);
00406
00407 return TRUE;
00408 }
00409
00422 void
00423 _dbus_connection_test_get_locks (DBusConnection *connection,
00424 DBusMutex **mutex_loc,
00425 DBusMutex **dispatch_mutex_loc,
00426 DBusMutex **io_path_mutex_loc,
00427 DBusCondVar **dispatch_cond_loc,
00428 DBusCondVar **io_path_cond_loc)
00429 {
00430 *mutex_loc = connection->mutex;
00431 *dispatch_mutex_loc = connection->dispatch_mutex;
00432 *io_path_mutex_loc = connection->io_path_mutex;
00433 *dispatch_cond_loc = connection->dispatch_cond;
00434 *io_path_cond_loc = connection->io_path_cond;
00435 }
00436 #endif
00437
00446 void
00447 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00448 DBusList *link)
00449 {
00450 DBusPendingCall *pending;
00451 dbus_int32_t reply_serial;
00452 DBusMessage *message;
00453
00454 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00455
00456 _dbus_list_append_link (&connection->incoming_messages,
00457 link);
00458 message = link->data;
00459
00460
00461 reply_serial = dbus_message_get_reply_serial (message);
00462 if (reply_serial != -1)
00463 {
00464 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00465 reply_serial);
00466 if (pending != NULL)
00467 {
00468 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00469 _dbus_connection_remove_timeout_unlocked (connection,
00470 _dbus_pending_call_get_timeout_unlocked (pending));
00471
00472 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00473 }
00474 }
00475
00476
00477
00478 connection->n_incoming += 1;
00479
00480 _dbus_connection_wakeup_mainloop (connection);
00481
00482 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00483 message,
00484 dbus_message_get_type (message),
00485 dbus_message_get_path (message) ?
00486 dbus_message_get_path (message) :
00487 "no path",
00488 dbus_message_get_interface (message) ?
00489 dbus_message_get_interface (message) :
00490 "no interface",
00491 dbus_message_get_member (message) ?
00492 dbus_message_get_member (message) :
00493 "no member",
00494 dbus_message_get_signature (message),
00495 dbus_message_get_reply_serial (message),
00496 connection,
00497 connection->n_incoming);}
00498
00507 void
00508 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00509 DBusList *link)
00510 {
00511 HAVE_LOCK_CHECK (connection);
00512
00513 _dbus_list_append_link (&connection->incoming_messages, link);
00514
00515 connection->n_incoming += 1;
00516
00517 _dbus_connection_wakeup_mainloop (connection);
00518
00519 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00520 link->data, connection, connection->n_incoming);
00521 }
00522
00523
00531 dbus_bool_t
00532 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00533 {
00534 HAVE_LOCK_CHECK (connection);
00535 return connection->outgoing_messages != NULL;
00536 }
00537
00547 dbus_bool_t
00548 dbus_connection_has_messages_to_send (DBusConnection *connection)
00549 {
00550 dbus_bool_t v;
00551
00552 _dbus_return_val_if_fail (connection != NULL, FALSE);
00553
00554 CONNECTION_LOCK (connection);
00555 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00556 CONNECTION_UNLOCK (connection);
00557
00558 return v;
00559 }
00560
00568 DBusMessage*
00569 _dbus_connection_get_message_to_send (DBusConnection *connection)
00570 {
00571 HAVE_LOCK_CHECK (connection);
00572
00573 return _dbus_list_get_last (&connection->outgoing_messages);
00574 }
00575
00584 void
00585 _dbus_connection_message_sent (DBusConnection *connection,
00586 DBusMessage *message)
00587 {
00588 DBusList *link;
00589
00590 HAVE_LOCK_CHECK (connection);
00591
00592
00593
00594
00595
00596
00597 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00598 _dbus_assert (link != NULL);
00599 _dbus_assert (link->data == message);
00600
00601
00602 _dbus_list_unlink (&connection->outgoing_messages,
00603 link);
00604 _dbus_list_prepend_link (&connection->link_cache, link);
00605
00606 connection->n_outgoing -= 1;
00607
00608 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00609 message,
00610 dbus_message_get_type (message),
00611 dbus_message_get_path (message) ?
00612 dbus_message_get_path (message) :
00613 "no path",
00614 dbus_message_get_interface (message) ?
00615 dbus_message_get_interface (message) :
00616 "no interface",
00617 dbus_message_get_member (message) ?
00618 dbus_message_get_member (message) :
00619 "no member",
00620 dbus_message_get_signature (message),
00621 connection, connection->n_outgoing);
00622
00623
00624 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00625 &link);
00626 _dbus_list_prepend_link (&connection->link_cache, link);
00627
00628 dbus_message_unref (message);
00629 }
00630
00632 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00633 DBusWatch *watch);
00635 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00636 DBusWatch *watch);
00638 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00639 DBusWatch *watch,
00640 dbus_bool_t enabled);
00641
00642 static dbus_bool_t
00643 protected_change_watch (DBusConnection *connection,
00644 DBusWatch *watch,
00645 DBusWatchAddFunction add_function,
00646 DBusWatchRemoveFunction remove_function,
00647 DBusWatchToggleFunction toggle_function,
00648 dbus_bool_t enabled)
00649 {
00650 DBusWatchList *watches;
00651 dbus_bool_t retval;
00652
00653 HAVE_LOCK_CHECK (connection);
00654
00655
00656
00657
00658
00659 watches = connection->watches;
00660 if (watches)
00661 {
00662 connection->watches = NULL;
00663 _dbus_connection_ref_unlocked (connection);
00664 CONNECTION_UNLOCK (connection);
00665
00666 if (add_function)
00667 retval = (* add_function) (watches, watch);
00668 else if (remove_function)
00669 {
00670 retval = TRUE;
00671 (* remove_function) (watches, watch);
00672 }
00673 else
00674 {
00675 retval = TRUE;
00676 (* toggle_function) (watches, watch, enabled);
00677 }
00678
00679 CONNECTION_LOCK (connection);
00680 connection->watches = watches;
00681 _dbus_connection_unref_unlocked (connection);
00682
00683 return retval;
00684 }
00685 else
00686 return FALSE;
00687 }
00688
00689
00701 dbus_bool_t
00702 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00703 DBusWatch *watch)
00704 {
00705 return protected_change_watch (connection, watch,
00706 _dbus_watch_list_add_watch,
00707 NULL, NULL, FALSE);
00708 }
00709
00719 void
00720 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00721 DBusWatch *watch)
00722 {
00723 protected_change_watch (connection, watch,
00724 NULL,
00725 _dbus_watch_list_remove_watch,
00726 NULL, FALSE);
00727 }
00728
00739 void
00740 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00741 DBusWatch *watch,
00742 dbus_bool_t enabled)
00743 {
00744 _dbus_assert (watch != NULL);
00745
00746 protected_change_watch (connection, watch,
00747 NULL, NULL,
00748 _dbus_watch_list_toggle_watch,
00749 enabled);
00750 }
00751
00753 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00754 DBusTimeout *timeout);
00756 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00757 DBusTimeout *timeout);
00759 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00760 DBusTimeout *timeout,
00761 dbus_bool_t enabled);
00762
00763 static dbus_bool_t
00764 protected_change_timeout (DBusConnection *connection,
00765 DBusTimeout *timeout,
00766 DBusTimeoutAddFunction add_function,
00767 DBusTimeoutRemoveFunction remove_function,
00768 DBusTimeoutToggleFunction toggle_function,
00769 dbus_bool_t enabled)
00770 {
00771 DBusTimeoutList *timeouts;
00772 dbus_bool_t retval;
00773
00774 HAVE_LOCK_CHECK (connection);
00775
00776
00777
00778
00779
00780 timeouts = connection->timeouts;
00781 if (timeouts)
00782 {
00783 connection->timeouts = NULL;
00784 _dbus_connection_ref_unlocked (connection);
00785 CONNECTION_UNLOCK (connection);
00786
00787 if (add_function)
00788 retval = (* add_function) (timeouts, timeout);
00789 else if (remove_function)
00790 {
00791 retval = TRUE;
00792 (* remove_function) (timeouts, timeout);
00793 }
00794 else
00795 {
00796 retval = TRUE;
00797 (* toggle_function) (timeouts, timeout, enabled);
00798 }
00799
00800 CONNECTION_LOCK (connection);
00801 connection->timeouts = timeouts;
00802 _dbus_connection_unref_unlocked (connection);
00803
00804 return retval;
00805 }
00806 else
00807 return FALSE;
00808 }
00809
00822 dbus_bool_t
00823 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00824 DBusTimeout *timeout)
00825 {
00826 return protected_change_timeout (connection, timeout,
00827 _dbus_timeout_list_add_timeout,
00828 NULL, NULL, FALSE);
00829 }
00830
00840 void
00841 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00842 DBusTimeout *timeout)
00843 {
00844 protected_change_timeout (connection, timeout,
00845 NULL,
00846 _dbus_timeout_list_remove_timeout,
00847 NULL, FALSE);
00848 }
00849
00860 void
00861 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00862 DBusTimeout *timeout,
00863 dbus_bool_t enabled)
00864 {
00865 protected_change_timeout (connection, timeout,
00866 NULL, NULL,
00867 _dbus_timeout_list_toggle_timeout,
00868 enabled);
00869 }
00870
00871 static dbus_bool_t
00872 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00873 DBusPendingCall *pending)
00874 {
00875 dbus_uint32_t reply_serial;
00876 DBusTimeout *timeout;
00877
00878 HAVE_LOCK_CHECK (connection);
00879
00880 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00881
00882 _dbus_assert (reply_serial != 0);
00883
00884 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00885
00886 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00887 return FALSE;
00888
00889 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00890 reply_serial,
00891 pending))
00892 {
00893 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00894
00895 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00896 HAVE_LOCK_CHECK (connection);
00897 return FALSE;
00898 }
00899
00900 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00901
00902 _dbus_pending_call_ref_unlocked (pending);
00903
00904 HAVE_LOCK_CHECK (connection);
00905
00906 return TRUE;
00907 }
00908
00909 static void
00910 free_pending_call_on_hash_removal (void *data)
00911 {
00912 DBusPendingCall *pending;
00913 DBusConnection *connection;
00914
00915 if (data == NULL)
00916 return;
00917
00918 pending = data;
00919
00920 connection = _dbus_pending_call_get_connection_unlocked (pending);
00921
00922 HAVE_LOCK_CHECK (connection);
00923
00924 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00925 {
00926 _dbus_connection_remove_timeout_unlocked (connection,
00927 _dbus_pending_call_get_timeout_unlocked (pending));
00928
00929 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00930 }
00931
00932
00933
00934
00935
00936
00937 _dbus_connection_ref_unlocked (connection);
00938 _dbus_pending_call_unref_and_unlock (pending);
00939 CONNECTION_LOCK (connection);
00940 _dbus_connection_unref_unlocked (connection);
00941 }
00942
00943 static void
00944 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00945 DBusPendingCall *pending)
00946 {
00947
00948
00949
00950 _dbus_hash_table_remove_int (connection->pending_replies,
00951 _dbus_pending_call_get_reply_serial_unlocked (pending));
00952 }
00953
00954 static void
00955 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00956 DBusPendingCall *pending)
00957 {
00958
00959
00960
00961
00962
00963
00964
00965 _dbus_pending_call_ref_unlocked (pending);
00966 _dbus_hash_table_remove_int (connection->pending_replies,
00967 _dbus_pending_call_get_reply_serial_unlocked (pending));
00968 _dbus_pending_call_unref_and_unlock (pending);
00969 }
00970
00979 void
00980 _dbus_connection_remove_pending_call (DBusConnection *connection,
00981 DBusPendingCall *pending)
00982 {
00983 CONNECTION_LOCK (connection);
00984 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00985 }
00986
00996 static dbus_bool_t
00997 _dbus_connection_acquire_io_path (DBusConnection *connection,
00998 int timeout_milliseconds)
00999 {
01000 dbus_bool_t we_acquired;
01001
01002 HAVE_LOCK_CHECK (connection);
01003
01004
01005 _dbus_connection_ref_unlocked (connection);
01006
01007
01008 CONNECTION_UNLOCK (connection);
01009
01010 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01011 _dbus_mutex_lock (connection->io_path_mutex);
01012
01013 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01014 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01015
01016 we_acquired = FALSE;
01017
01018 if (connection->io_path_acquired)
01019 {
01020 if (timeout_milliseconds != -1)
01021 {
01022 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01023 _DBUS_FUNCTION_NAME, timeout_milliseconds);
01024
01025 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01026 connection->io_path_mutex,
01027 timeout_milliseconds))
01028 {
01029
01030
01031
01032
01033
01034
01035
01036
01037 }
01038 }
01039 else
01040 {
01041 while (connection->io_path_acquired)
01042 {
01043 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01044 _dbus_condvar_wait (connection->io_path_cond,
01045 connection->io_path_mutex);
01046 }
01047 }
01048 }
01049
01050 if (!connection->io_path_acquired)
01051 {
01052 we_acquired = TRUE;
01053 connection->io_path_acquired = TRUE;
01054 }
01055
01056 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01057 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01058
01059 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01060 _dbus_mutex_unlock (connection->io_path_mutex);
01061
01062 CONNECTION_LOCK (connection);
01063
01064 HAVE_LOCK_CHECK (connection);
01065
01066 _dbus_connection_unref_unlocked (connection);
01067
01068 return we_acquired;
01069 }
01070
01078 static void
01079 _dbus_connection_release_io_path (DBusConnection *connection)
01080 {
01081 HAVE_LOCK_CHECK (connection);
01082
01083 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01084 _dbus_mutex_lock (connection->io_path_mutex);
01085
01086 _dbus_assert (connection->io_path_acquired);
01087
01088 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01089 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01090
01091 connection->io_path_acquired = FALSE;
01092 _dbus_condvar_wake_one (connection->io_path_cond);
01093
01094 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01095 _dbus_mutex_unlock (connection->io_path_mutex);
01096 }
01097
01126 void
01127 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01128 unsigned int flags,
01129 int timeout_milliseconds)
01130 {
01131 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01132
01133 HAVE_LOCK_CHECK (connection);
01134
01135 if (connection->n_outgoing == 0)
01136 flags &= ~DBUS_ITERATION_DO_WRITING;
01137
01138 if (_dbus_connection_acquire_io_path (connection,
01139 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01140 {
01141 HAVE_LOCK_CHECK (connection);
01142
01143 _dbus_transport_do_iteration (connection->transport,
01144 flags, timeout_milliseconds);
01145 _dbus_connection_release_io_path (connection);
01146 }
01147
01148 HAVE_LOCK_CHECK (connection);
01149
01150 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01151 }
01152
01162 DBusConnection*
01163 _dbus_connection_new_for_transport (DBusTransport *transport)
01164 {
01165 DBusConnection *connection;
01166 DBusWatchList *watch_list;
01167 DBusTimeoutList *timeout_list;
01168 DBusHashTable *pending_replies;
01169 DBusList *disconnect_link;
01170 DBusMessage *disconnect_message;
01171 DBusCounter *outgoing_counter;
01172 DBusObjectTree *objects;
01173
01174 watch_list = NULL;
01175 connection = NULL;
01176 pending_replies = NULL;
01177 timeout_list = NULL;
01178 disconnect_link = NULL;
01179 disconnect_message = NULL;
01180 outgoing_counter = NULL;
01181 objects = NULL;
01182
01183 watch_list = _dbus_watch_list_new ();
01184 if (watch_list == NULL)
01185 goto error;
01186
01187 timeout_list = _dbus_timeout_list_new ();
01188 if (timeout_list == NULL)
01189 goto error;
01190
01191 pending_replies =
01192 _dbus_hash_table_new (DBUS_HASH_INT,
01193 NULL,
01194 (DBusFreeFunction)free_pending_call_on_hash_removal);
01195 if (pending_replies == NULL)
01196 goto error;
01197
01198 connection = dbus_new0 (DBusConnection, 1);
01199 if (connection == NULL)
01200 goto error;
01201
01202 _dbus_mutex_new_at_location (&connection->mutex);
01203 if (connection->mutex == NULL)
01204 goto error;
01205
01206 _dbus_mutex_new_at_location (&connection->io_path_mutex);
01207 if (connection->io_path_mutex == NULL)
01208 goto error;
01209
01210 _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01211 if (connection->dispatch_mutex == NULL)
01212 goto error;
01213
01214 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01215 if (connection->dispatch_cond == NULL)
01216 goto error;
01217
01218 _dbus_condvar_new_at_location (&connection->io_path_cond);
01219 if (connection->io_path_cond == NULL)
01220 goto error;
01221
01222 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01223 DBUS_INTERFACE_LOCAL,
01224 "Disconnected");
01225
01226 if (disconnect_message == NULL)
01227 goto error;
01228
01229 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01230 if (disconnect_link == NULL)
01231 goto error;
01232
01233 outgoing_counter = _dbus_counter_new ();
01234 if (outgoing_counter == NULL)
01235 goto error;
01236
01237 objects = _dbus_object_tree_new (connection);
01238 if (objects == NULL)
01239 goto error;
01240
01241 if (_dbus_modify_sigpipe)
01242 _dbus_disable_sigpipe ();
01243
01244 connection->refcount.value = 1;
01245 connection->transport = transport;
01246 connection->watches = watch_list;
01247 connection->timeouts = timeout_list;
01248 connection->pending_replies = pending_replies;
01249 connection->outgoing_counter = outgoing_counter;
01250 connection->filter_list = NULL;
01251 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01252 connection->objects = objects;
01253 connection->exit_on_disconnect = FALSE;
01254 connection->shareable = FALSE;
01255 connection->route_peer_messages = FALSE;
01256 connection->disconnected_message_arrived = FALSE;
01257 connection->disconnected_message_processed = FALSE;
01258
01259 #ifndef DBUS_DISABLE_CHECKS
01260 connection->generation = _dbus_current_generation;
01261 #endif
01262
01263 _dbus_data_slot_list_init (&connection->slot_list);
01264
01265 connection->client_serial = 1;
01266
01267 connection->disconnect_message_link = disconnect_link;
01268
01269 CONNECTION_LOCK (connection);
01270
01271 if (!_dbus_transport_set_connection (transport, connection))
01272 {
01273 CONNECTION_UNLOCK (connection);
01274
01275 goto error;
01276 }
01277
01278 _dbus_transport_ref (transport);
01279
01280 CONNECTION_UNLOCK (connection);
01281
01282 return connection;
01283
01284 error:
01285 if (disconnect_message != NULL)
01286 dbus_message_unref (disconnect_message);
01287
01288 if (disconnect_link != NULL)
01289 _dbus_list_free_link (disconnect_link);
01290
01291 if (connection != NULL)
01292 {
01293 _dbus_condvar_free_at_location (&connection->io_path_cond);
01294 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01295 _dbus_mutex_free_at_location (&connection->mutex);
01296 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01297 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01298 dbus_free (connection);
01299 }
01300 if (pending_replies)
01301 _dbus_hash_table_unref (pending_replies);
01302
01303 if (watch_list)
01304 _dbus_watch_list_free (watch_list);
01305
01306 if (timeout_list)
01307 _dbus_timeout_list_free (timeout_list);
01308
01309 if (outgoing_counter)
01310 _dbus_counter_unref (outgoing_counter);
01311
01312 if (objects)
01313 _dbus_object_tree_unref (objects);
01314
01315 return NULL;
01316 }
01317
01325 DBusConnection *
01326 _dbus_connection_ref_unlocked (DBusConnection *connection)
01327 {
01328 _dbus_assert (connection != NULL);
01329 _dbus_assert (connection->generation == _dbus_current_generation);
01330
01331 HAVE_LOCK_CHECK (connection);
01332
01333 #ifdef DBUS_HAVE_ATOMIC_INT
01334 _dbus_atomic_inc (&connection->refcount);
01335 #else
01336 _dbus_assert (connection->refcount.value > 0);
01337 connection->refcount.value += 1;
01338 #endif
01339
01340 return connection;
01341 }
01342
01349 void
01350 _dbus_connection_unref_unlocked (DBusConnection *connection)
01351 {
01352 dbus_bool_t last_unref;
01353
01354 HAVE_LOCK_CHECK (connection);
01355
01356 _dbus_assert (connection != NULL);
01357
01358
01359
01360
01361
01362 #ifdef DBUS_HAVE_ATOMIC_INT
01363 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01364 #else
01365 _dbus_assert (connection->refcount.value > 0);
01366
01367 connection->refcount.value -= 1;
01368 last_unref = (connection->refcount.value == 0);
01369 #if 0
01370 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01371 #endif
01372 #endif
01373
01374 if (last_unref)
01375 _dbus_connection_last_unref (connection);
01376 }
01377
01378 static dbus_uint32_t
01379 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01380 {
01381 dbus_uint32_t serial;
01382
01383 serial = connection->client_serial++;
01384
01385 if (connection->client_serial == 0)
01386 connection->client_serial = 1;
01387
01388 return serial;
01389 }
01390
01404 dbus_bool_t
01405 _dbus_connection_handle_watch (DBusWatch *watch,
01406 unsigned int condition,
01407 void *data)
01408 {
01409 DBusConnection *connection;
01410 dbus_bool_t retval;
01411 DBusDispatchStatus status;
01412
01413 connection = data;
01414
01415 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01416
01417 CONNECTION_LOCK (connection);
01418 _dbus_connection_acquire_io_path (connection, -1);
01419 HAVE_LOCK_CHECK (connection);
01420 retval = _dbus_transport_handle_watch (connection->transport,
01421 watch, condition);
01422
01423 _dbus_connection_release_io_path (connection);
01424
01425 HAVE_LOCK_CHECK (connection);
01426
01427 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01428
01429 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01430
01431
01432 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01433
01434 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01435
01436 return retval;
01437 }
01438
01439 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01440 static DBusHashTable *shared_connections = NULL;
01441 static DBusList *shared_connections_no_guid = NULL;
01442
01443 static void
01444 close_connection_on_shutdown (DBusConnection *connection)
01445 {
01446 DBusMessage *message;
01447
01448 dbus_connection_ref (connection);
01449 _dbus_connection_close_possibly_shared (connection);
01450
01451
01452 while ((message = dbus_connection_pop_message (connection)))
01453 {
01454 dbus_message_unref (message);
01455 }
01456 dbus_connection_unref (connection);
01457 }
01458
01459 static void
01460 shared_connections_shutdown (void *data)
01461 {
01462 int n_entries;
01463
01464 _DBUS_LOCK (shared_connections);
01465
01466
01467 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01468 {
01469 DBusConnection *connection;
01470 DBusHashIter iter;
01471
01472 _dbus_hash_iter_init (shared_connections, &iter);
01473 _dbus_hash_iter_next (&iter);
01474
01475 connection = _dbus_hash_iter_get_value (&iter);
01476
01477 _DBUS_UNLOCK (shared_connections);
01478 close_connection_on_shutdown (connection);
01479 _DBUS_LOCK (shared_connections);
01480
01481
01482 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01483 }
01484
01485 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01486
01487 _dbus_hash_table_unref (shared_connections);
01488 shared_connections = NULL;
01489
01490 if (shared_connections_no_guid != NULL)
01491 {
01492 DBusConnection *connection;
01493 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01494 while (connection != NULL)
01495 {
01496 _DBUS_UNLOCK (shared_connections);
01497 close_connection_on_shutdown (connection);
01498 _DBUS_LOCK (shared_connections);
01499 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01500 }
01501 }
01502
01503 shared_connections_no_guid = NULL;
01504
01505 _DBUS_UNLOCK (shared_connections);
01506 }
01507
01508 static dbus_bool_t
01509 connection_lookup_shared (DBusAddressEntry *entry,
01510 DBusConnection **result)
01511 {
01512 _dbus_verbose ("checking for existing connection\n");
01513
01514 *result = NULL;
01515
01516 _DBUS_LOCK (shared_connections);
01517
01518 if (shared_connections == NULL)
01519 {
01520 _dbus_verbose ("creating shared_connections hash table\n");
01521
01522 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01523 dbus_free,
01524 NULL);
01525 if (shared_connections == NULL)
01526 {
01527 _DBUS_UNLOCK (shared_connections);
01528 return FALSE;
01529 }
01530
01531 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01532 {
01533 _dbus_hash_table_unref (shared_connections);
01534 shared_connections = NULL;
01535 _DBUS_UNLOCK (shared_connections);
01536 return FALSE;
01537 }
01538
01539 _dbus_verbose (" successfully created shared_connections\n");
01540
01541 _DBUS_UNLOCK (shared_connections);
01542 return TRUE;
01543 }
01544 else
01545 {
01546 const char *guid;
01547
01548 guid = dbus_address_entry_get_value (entry, "guid");
01549
01550 if (guid != NULL)
01551 {
01552 DBusConnection *connection;
01553
01554 connection = _dbus_hash_table_lookup_string (shared_connections,
01555 guid);
01556
01557 if (connection)
01558 {
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 CONNECTION_LOCK (connection);
01574 if (_dbus_connection_get_is_connected_unlocked (connection))
01575 {
01576 _dbus_connection_ref_unlocked (connection);
01577 *result = connection;
01578 _dbus_verbose ("looked up existing connection to server guid %s\n",
01579 guid);
01580 }
01581 else
01582 {
01583 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01584 guid);
01585 }
01586 CONNECTION_UNLOCK (connection);
01587 }
01588 }
01589
01590 _DBUS_UNLOCK (shared_connections);
01591 return TRUE;
01592 }
01593 }
01594
01595 static dbus_bool_t
01596 connection_record_shared_unlocked (DBusConnection *connection,
01597 const char *guid)
01598 {
01599 char *guid_key;
01600 char *guid_in_connection;
01601
01602 HAVE_LOCK_CHECK (connection);
01603 _dbus_assert (connection->server_guid == NULL);
01604 _dbus_assert (connection->shareable);
01605
01606
01607
01608
01609
01610 _dbus_connection_ref_unlocked (connection);
01611
01612 if (guid == NULL)
01613 {
01614 _DBUS_LOCK (shared_connections);
01615
01616 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01617 {
01618 _DBUS_UNLOCK (shared_connections);
01619 return FALSE;
01620 }
01621
01622 _DBUS_UNLOCK (shared_connections);
01623 return TRUE;
01624 }
01625
01626
01627
01628
01629
01630
01631 guid_key = _dbus_strdup (guid);
01632 if (guid_key == NULL)
01633 return FALSE;
01634
01635 guid_in_connection = _dbus_strdup (guid);
01636 if (guid_in_connection == NULL)
01637 {
01638 dbus_free (guid_key);
01639 return FALSE;
01640 }
01641
01642 _DBUS_LOCK (shared_connections);
01643 _dbus_assert (shared_connections != NULL);
01644
01645 if (!_dbus_hash_table_insert_string (shared_connections,
01646 guid_key, connection))
01647 {
01648 dbus_free (guid_key);
01649 dbus_free (guid_in_connection);
01650 _DBUS_UNLOCK (shared_connections);
01651 return FALSE;
01652 }
01653
01654 connection->server_guid = guid_in_connection;
01655
01656 _dbus_verbose ("stored connection to %s to be shared\n",
01657 connection->server_guid);
01658
01659 _DBUS_UNLOCK (shared_connections);
01660
01661 _dbus_assert (connection->server_guid != NULL);
01662
01663 return TRUE;
01664 }
01665
01666 static void
01667 connection_forget_shared_unlocked (DBusConnection *connection)
01668 {
01669 HAVE_LOCK_CHECK (connection);
01670
01671 if (!connection->shareable)
01672 return;
01673
01674 if (connection->server_guid != NULL)
01675 {
01676 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01677 connection->server_guid);
01678
01679 _DBUS_LOCK (shared_connections);
01680
01681 if (!_dbus_hash_table_remove_string (shared_connections,
01682 connection->server_guid))
01683 _dbus_assert_not_reached ("connection was not in the shared table");
01684
01685 dbus_free (connection->server_guid);
01686 connection->server_guid = NULL;
01687 _DBUS_UNLOCK (shared_connections);
01688 }
01689
01690
01691 _dbus_connection_unref_unlocked (connection);
01692 }
01693
01694 static DBusConnection*
01695 connection_try_from_address_entry (DBusAddressEntry *entry,
01696 DBusError *error)
01697 {
01698 DBusTransport *transport;
01699 DBusConnection *connection;
01700
01701 transport = _dbus_transport_open (entry, error);
01702
01703 if (transport == NULL)
01704 {
01705 _DBUS_ASSERT_ERROR_IS_SET (error);
01706 return NULL;
01707 }
01708
01709 connection = _dbus_connection_new_for_transport (transport);
01710
01711 _dbus_transport_unref (transport);
01712
01713 if (connection == NULL)
01714 {
01715 _DBUS_SET_OOM (error);
01716 return NULL;
01717 }
01718
01719 #ifndef DBUS_DISABLE_CHECKS
01720 _dbus_assert (!connection->have_connection_lock);
01721 #endif
01722 return connection;
01723 }
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737 static DBusConnection*
01738 _dbus_connection_open_internal (const char *address,
01739 dbus_bool_t shared,
01740 DBusError *error)
01741 {
01742 DBusConnection *connection;
01743 DBusAddressEntry **entries;
01744 DBusError tmp_error = DBUS_ERROR_INIT;
01745 DBusError first_error = DBUS_ERROR_INIT;
01746 int len, i;
01747
01748 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01749
01750 _dbus_verbose ("opening %s connection to: %s\n",
01751 shared ? "shared" : "private", address);
01752
01753 if (!dbus_parse_address (address, &entries, &len, error))
01754 return NULL;
01755
01756 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01757
01758 connection = NULL;
01759
01760 for (i = 0; i < len; i++)
01761 {
01762 if (shared)
01763 {
01764 if (!connection_lookup_shared (entries[i], &connection))
01765 _DBUS_SET_OOM (&tmp_error);
01766 }
01767
01768 if (connection == NULL)
01769 {
01770 connection = connection_try_from_address_entry (entries[i],
01771 &tmp_error);
01772
01773 if (connection != NULL && shared)
01774 {
01775 const char *guid;
01776
01777 connection->shareable = TRUE;
01778
01779
01780 guid = dbus_address_entry_get_value (entries[i], "guid");
01781
01782 CONNECTION_LOCK (connection);
01783
01784 if (!connection_record_shared_unlocked (connection, guid))
01785 {
01786 _DBUS_SET_OOM (&tmp_error);
01787 _dbus_connection_close_possibly_shared_and_unlock (connection);
01788 dbus_connection_unref (connection);
01789 connection = NULL;
01790 }
01791 else
01792 CONNECTION_UNLOCK (connection);
01793 }
01794 }
01795
01796 if (connection)
01797 break;
01798
01799 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01800
01801 if (i == 0)
01802 dbus_move_error (&tmp_error, &first_error);
01803 else
01804 dbus_error_free (&tmp_error);
01805 }
01806
01807 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01808 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01809
01810 if (connection == NULL)
01811 {
01812 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01813 dbus_move_error (&first_error, error);
01814 }
01815 else
01816 dbus_error_free (&first_error);
01817
01818 dbus_address_entries_free (entries);
01819 return connection;
01820 }
01821
01830 void
01831 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01832 {
01833 _dbus_assert (connection != NULL);
01834 _dbus_assert (connection->generation == _dbus_current_generation);
01835
01836 CONNECTION_LOCK (connection);
01837 _dbus_connection_close_possibly_shared_and_unlock (connection);
01838 }
01839
01840 static DBusPreallocatedSend*
01841 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01842 {
01843 DBusPreallocatedSend *preallocated;
01844
01845 HAVE_LOCK_CHECK (connection);
01846
01847 _dbus_assert (connection != NULL);
01848
01849 preallocated = dbus_new (DBusPreallocatedSend, 1);
01850 if (preallocated == NULL)
01851 return NULL;
01852
01853 if (connection->link_cache != NULL)
01854 {
01855 preallocated->queue_link =
01856 _dbus_list_pop_first_link (&connection->link_cache);
01857 preallocated->queue_link->data = NULL;
01858 }
01859 else
01860 {
01861 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01862 if (preallocated->queue_link == NULL)
01863 goto failed_0;
01864 }
01865
01866 if (connection->link_cache != NULL)
01867 {
01868 preallocated->counter_link =
01869 _dbus_list_pop_first_link (&connection->link_cache);
01870 preallocated->counter_link->data = connection->outgoing_counter;
01871 }
01872 else
01873 {
01874 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01875 if (preallocated->counter_link == NULL)
01876 goto failed_1;
01877 }
01878
01879 _dbus_counter_ref (preallocated->counter_link->data);
01880
01881 preallocated->connection = connection;
01882
01883 return preallocated;
01884
01885 failed_1:
01886 _dbus_list_free_link (preallocated->queue_link);
01887 failed_0:
01888 dbus_free (preallocated);
01889
01890 return NULL;
01891 }
01892
01893
01894 static void
01895 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01896 DBusPreallocatedSend *preallocated,
01897 DBusMessage *message,
01898 dbus_uint32_t *client_serial)
01899 {
01900 dbus_uint32_t serial;
01901 const char *sig;
01902
01903 preallocated->queue_link->data = message;
01904 _dbus_list_prepend_link (&connection->outgoing_messages,
01905 preallocated->queue_link);
01906
01907 _dbus_message_add_size_counter_link (message,
01908 preallocated->counter_link);
01909
01910 dbus_free (preallocated);
01911 preallocated = NULL;
01912
01913 dbus_message_ref (message);
01914
01915 connection->n_outgoing += 1;
01916
01917 sig = dbus_message_get_signature (message);
01918
01919 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01920 message,
01921 dbus_message_get_type (message),
01922 dbus_message_get_path (message) ?
01923 dbus_message_get_path (message) :
01924 "no path",
01925 dbus_message_get_interface (message) ?
01926 dbus_message_get_interface (message) :
01927 "no interface",
01928 dbus_message_get_member (message) ?
01929 dbus_message_get_member (message) :
01930 "no member",
01931 sig,
01932 dbus_message_get_destination (message) ?
01933 dbus_message_get_destination (message) :
01934 "null",
01935 connection,
01936 connection->n_outgoing);
01937
01938 if (dbus_message_get_serial (message) == 0)
01939 {
01940 serial = _dbus_connection_get_next_client_serial (connection);
01941 _dbus_message_set_serial (message, serial);
01942 if (client_serial)
01943 *client_serial = serial;
01944 }
01945 else
01946 {
01947 if (client_serial)
01948 *client_serial = dbus_message_get_serial (message);
01949 }
01950
01951 _dbus_verbose ("Message %p serial is %u\n",
01952 message, dbus_message_get_serial (message));
01953
01954 _dbus_message_lock (message);
01955
01956
01957
01958
01959 _dbus_connection_do_iteration_unlocked (connection,
01960 DBUS_ITERATION_DO_WRITING,
01961 -1);
01962
01963
01964 if (connection->n_outgoing > 0)
01965 _dbus_connection_wakeup_mainloop (connection);
01966 }
01967
01968 static void
01969 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
01970 DBusPreallocatedSend *preallocated,
01971 DBusMessage *message,
01972 dbus_uint32_t *client_serial)
01973 {
01974 DBusDispatchStatus status;
01975
01976 HAVE_LOCK_CHECK (connection);
01977
01978 _dbus_connection_send_preallocated_unlocked_no_update (connection,
01979 preallocated,
01980 message, client_serial);
01981
01982 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01983 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01984
01985
01986 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01987 }
01988
01998 dbus_bool_t
01999 _dbus_connection_send_and_unlock (DBusConnection *connection,
02000 DBusMessage *message,
02001 dbus_uint32_t *client_serial)
02002 {
02003 DBusPreallocatedSend *preallocated;
02004
02005 _dbus_assert (connection != NULL);
02006 _dbus_assert (message != NULL);
02007
02008 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02009 if (preallocated == NULL)
02010 {
02011 CONNECTION_UNLOCK (connection);
02012 return FALSE;
02013 }
02014
02015 _dbus_connection_send_preallocated_and_unlock (connection,
02016 preallocated,
02017 message,
02018 client_serial);
02019 return TRUE;
02020 }
02021
02046 void
02047 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02048 {
02049 CONNECTION_LOCK (connection);
02050
02051 _dbus_assert (connection->refcount.value > 0);
02052
02053 if (connection->refcount.value == 1)
02054 _dbus_connection_close_possibly_shared_and_unlock (connection);
02055 else
02056 CONNECTION_UNLOCK (connection);
02057 }
02058
02059
02069 static void
02070 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02071 {
02072 if (timeout_milliseconds == -1)
02073 _dbus_sleep_milliseconds (1000);
02074 else if (timeout_milliseconds < 100)
02075 ;
02076 else if (timeout_milliseconds <= 1000)
02077 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02078 else
02079 _dbus_sleep_milliseconds (1000);
02080 }
02081
02082 static DBusMessage *
02083 generate_local_error_message (dbus_uint32_t serial,
02084 char *error_name,
02085 char *error_msg)
02086 {
02087 DBusMessage *message;
02088 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02089 if (!message)
02090 goto out;
02091
02092 if (!dbus_message_set_error_name (message, error_name))
02093 {
02094 dbus_message_unref (message);
02095 message = NULL;
02096 goto out;
02097 }
02098
02099 dbus_message_set_no_reply (message, TRUE);
02100
02101 if (!dbus_message_set_reply_serial (message,
02102 serial))
02103 {
02104 dbus_message_unref (message);
02105 message = NULL;
02106 goto out;
02107 }
02108
02109 if (error_msg != NULL)
02110 {
02111 DBusMessageIter iter;
02112
02113 dbus_message_iter_init_append (message, &iter);
02114 if (!dbus_message_iter_append_basic (&iter,
02115 DBUS_TYPE_STRING,
02116 &error_msg))
02117 {
02118 dbus_message_unref (message);
02119 message = NULL;
02120 goto out;
02121 }
02122 }
02123
02124 out:
02125 return message;
02126 }
02127
02128
02129
02130
02131
02132 static DBusMessage*
02133 check_for_reply_unlocked (DBusConnection *connection,
02134 dbus_uint32_t client_serial)
02135 {
02136 DBusList *link;
02137
02138 HAVE_LOCK_CHECK (connection);
02139
02140 link = _dbus_list_get_first_link (&connection->incoming_messages);
02141
02142 while (link != NULL)
02143 {
02144 DBusMessage *reply = link->data;
02145
02146 if (dbus_message_get_reply_serial (reply) == client_serial)
02147 {
02148 _dbus_list_remove_link (&connection->incoming_messages, link);
02149 connection->n_incoming -= 1;
02150 return reply;
02151 }
02152 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02153 }
02154
02155 return NULL;
02156 }
02157
02158 static void
02159 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02160 {
02161
02162
02163
02164
02165
02166 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02167 {
02168 DBusPendingCall *pending;
02169 DBusHashIter iter;
02170
02171 _dbus_hash_iter_init (connection->pending_replies, &iter);
02172 _dbus_hash_iter_next (&iter);
02173
02174 pending = _dbus_hash_iter_get_value (&iter);
02175 _dbus_pending_call_ref_unlocked (pending);
02176
02177 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02178 connection);
02179 _dbus_connection_remove_timeout_unlocked (connection,
02180 _dbus_pending_call_get_timeout_unlocked (pending));
02181 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02182 _dbus_hash_iter_remove_entry (&iter);
02183
02184 _dbus_pending_call_unref_and_unlock (pending);
02185 CONNECTION_LOCK (connection);
02186 }
02187 HAVE_LOCK_CHECK (connection);
02188 }
02189
02190 static void
02191 complete_pending_call_and_unlock (DBusConnection *connection,
02192 DBusPendingCall *pending,
02193 DBusMessage *message)
02194 {
02195 _dbus_pending_call_set_reply_unlocked (pending, message);
02196 _dbus_pending_call_ref_unlocked (pending);
02197 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02198
02199
02200 _dbus_pending_call_complete (pending);
02201 dbus_pending_call_unref (pending);
02202 }
02203
02204 static dbus_bool_t
02205 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02206 DBusPendingCall *pending)
02207 {
02208 DBusMessage *reply;
02209 DBusDispatchStatus status;
02210
02211 reply = check_for_reply_unlocked (connection,
02212 _dbus_pending_call_get_reply_serial_unlocked (pending));
02213 if (reply != NULL)
02214 {
02215 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02216
02217 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02218
02219 complete_pending_call_and_unlock (connection, pending, reply);
02220 dbus_message_unref (reply);
02221
02222 CONNECTION_LOCK (connection);
02223 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02224 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02225 dbus_pending_call_unref (pending);
02226
02227 return TRUE;
02228 }
02229
02230 return FALSE;
02231 }
02232
02247 void
02248 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02249 {
02250 long start_tv_sec, start_tv_usec;
02251 long end_tv_sec, end_tv_usec;
02252 long tv_sec, tv_usec;
02253 DBusDispatchStatus status;
02254 DBusConnection *connection;
02255 dbus_uint32_t client_serial;
02256 int timeout_milliseconds;
02257
02258 _dbus_assert (pending != NULL);
02259
02260 if (dbus_pending_call_get_completed (pending))
02261 return;
02262
02263 dbus_pending_call_ref (pending);
02264
02265 connection = _dbus_pending_call_get_connection_and_lock (pending);
02266
02267
02268 _dbus_connection_flush_unlocked (connection);
02269
02270 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02271
02272
02273
02274
02275
02276 timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02277
02278 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02279 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02280 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02281 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02282 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02283
02284 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n",
02285 timeout_milliseconds,
02286 client_serial,
02287 start_tv_sec, start_tv_usec,
02288 end_tv_sec, end_tv_usec);
02289
02290
02291
02292 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02293 return;
02294
02295
02296
02297 _dbus_connection_do_iteration_unlocked (connection,
02298 DBUS_ITERATION_DO_READING |
02299 DBUS_ITERATION_BLOCK,
02300 timeout_milliseconds);
02301
02302 recheck_status:
02303
02304 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02305
02306 HAVE_LOCK_CHECK (connection);
02307
02308
02309
02310 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02311
02312
02313
02314
02315 if (_dbus_pending_call_get_completed_unlocked (pending))
02316 {
02317 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02318 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02319 dbus_pending_call_unref (pending);
02320 return;
02321 }
02322
02323 if (status == DBUS_DISPATCH_DATA_REMAINS)
02324 {
02325 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02326 return;
02327 }
02328
02329 _dbus_get_current_time (&tv_sec, &tv_usec);
02330
02331 if (!_dbus_connection_get_is_connected_unlocked (connection))
02332 {
02333 DBusMessage *error_msg;
02334
02335 error_msg = generate_local_error_message (client_serial,
02336 DBUS_ERROR_DISCONNECTED,
02337 "Connection was disconnected before a reply was received");
02338
02339
02340 complete_pending_call_and_unlock (connection, pending, error_msg);
02341 dbus_pending_call_unref (pending);
02342 return;
02343 }
02344 else if (tv_sec < start_tv_sec)
02345 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02346 else if (connection->disconnect_message_link == NULL)
02347 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02348 else if (tv_sec < end_tv_sec ||
02349 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02350 {
02351 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02352 (end_tv_usec - tv_usec) / 1000;
02353 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02354 _dbus_assert (timeout_milliseconds >= 0);
02355
02356 if (status == DBUS_DISPATCH_NEED_MEMORY)
02357 {
02358
02359
02360
02361
02362 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02363
02364 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02365 }
02366 else
02367 {
02368
02369 _dbus_connection_do_iteration_unlocked (connection,
02370 DBUS_ITERATION_DO_READING |
02371 DBUS_ITERATION_BLOCK,
02372 timeout_milliseconds);
02373 }
02374
02375 goto recheck_status;
02376 }
02377
02378 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02379 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02380
02381 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02382
02383
02384 complete_pending_call_and_unlock (connection, pending, NULL);
02385
02386
02387 CONNECTION_LOCK (connection);
02388 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02389 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02390 dbus_pending_call_unref (pending);
02391 }
02392
02429 DBusConnection*
02430 dbus_connection_open (const char *address,
02431 DBusError *error)
02432 {
02433 DBusConnection *connection;
02434
02435 _dbus_return_val_if_fail (address != NULL, NULL);
02436 _dbus_return_val_if_error_is_set (error, NULL);
02437
02438 connection = _dbus_connection_open_internal (address,
02439 TRUE,
02440 error);
02441
02442 return connection;
02443 }
02444
02472 DBusConnection*
02473 dbus_connection_open_private (const char *address,
02474 DBusError *error)
02475 {
02476 DBusConnection *connection;
02477
02478 _dbus_return_val_if_fail (address != NULL, NULL);
02479 _dbus_return_val_if_error_is_set (error, NULL);
02480
02481 connection = _dbus_connection_open_internal (address,
02482 FALSE,
02483 error);
02484
02485 return connection;
02486 }
02487
02494 DBusConnection *
02495 dbus_connection_ref (DBusConnection *connection)
02496 {
02497 _dbus_return_val_if_fail (connection != NULL, NULL);
02498 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02499
02500
02501
02502
02503
02504 #ifdef DBUS_HAVE_ATOMIC_INT
02505 _dbus_atomic_inc (&connection->refcount);
02506 #else
02507 CONNECTION_LOCK (connection);
02508 _dbus_assert (connection->refcount.value > 0);
02509
02510 connection->refcount.value += 1;
02511 CONNECTION_UNLOCK (connection);
02512 #endif
02513
02514 return connection;
02515 }
02516
02517 static void
02518 free_outgoing_message (void *element,
02519 void *data)
02520 {
02521 DBusMessage *message = element;
02522 DBusConnection *connection = data;
02523
02524 _dbus_message_remove_size_counter (message,
02525 connection->outgoing_counter,
02526 NULL);
02527 dbus_message_unref (message);
02528 }
02529
02530
02531
02532
02533
02534 static void
02535 _dbus_connection_last_unref (DBusConnection *connection)
02536 {
02537 DBusList *link;
02538
02539 _dbus_verbose ("Finalizing connection %p\n", connection);
02540
02541 _dbus_assert (connection->refcount.value == 0);
02542
02543
02544
02545
02546 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02547 _dbus_assert (connection->server_guid == NULL);
02548
02549
02550 _dbus_object_tree_free_all_unlocked (connection->objects);
02551
02552 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02553 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02554 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02555
02556 _dbus_watch_list_free (connection->watches);
02557 connection->watches = NULL;
02558
02559 _dbus_timeout_list_free (connection->timeouts);
02560 connection->timeouts = NULL;
02561
02562 _dbus_data_slot_list_free (&connection->slot_list);
02563
02564 link = _dbus_list_get_first_link (&connection->filter_list);
02565 while (link != NULL)
02566 {
02567 DBusMessageFilter *filter = link->data;
02568 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02569
02570 filter->function = NULL;
02571 _dbus_message_filter_unref (filter);
02572 link->data = NULL;
02573
02574 link = next;
02575 }
02576 _dbus_list_clear (&connection->filter_list);
02577
02578
02579
02580 _dbus_object_tree_unref (connection->objects);
02581
02582 _dbus_hash_table_unref (connection->pending_replies);
02583 connection->pending_replies = NULL;
02584
02585 _dbus_list_clear (&connection->filter_list);
02586
02587 _dbus_list_foreach (&connection->outgoing_messages,
02588 free_outgoing_message,
02589 connection);
02590 _dbus_list_clear (&connection->outgoing_messages);
02591
02592 _dbus_list_foreach (&connection->incoming_messages,
02593 (DBusForeachFunction) dbus_message_unref,
02594 NULL);
02595 _dbus_list_clear (&connection->incoming_messages);
02596
02597 _dbus_counter_unref (connection->outgoing_counter);
02598
02599 _dbus_transport_unref (connection->transport);
02600
02601 if (connection->disconnect_message_link)
02602 {
02603 DBusMessage *message = connection->disconnect_message_link->data;
02604 dbus_message_unref (message);
02605 _dbus_list_free_link (connection->disconnect_message_link);
02606 }
02607
02608 _dbus_list_clear (&connection->link_cache);
02609
02610 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02611 _dbus_condvar_free_at_location (&connection->io_path_cond);
02612
02613 _dbus_mutex_free_at_location (&connection->io_path_mutex);
02614 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02615
02616 _dbus_mutex_free_at_location (&connection->mutex);
02617
02618 dbus_free (connection);
02619 }
02620
02640 void
02641 dbus_connection_unref (DBusConnection *connection)
02642 {
02643 dbus_bool_t last_unref;
02644
02645 _dbus_return_if_fail (connection != NULL);
02646 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02647
02648
02649
02650
02651
02652 #ifdef DBUS_HAVE_ATOMIC_INT
02653 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02654 #else
02655 CONNECTION_LOCK (connection);
02656
02657 _dbus_assert (connection->refcount.value > 0);
02658
02659 connection->refcount.value -= 1;
02660 last_unref = (connection->refcount.value == 0);
02661
02662 #if 0
02663 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02664 #endif
02665
02666 CONNECTION_UNLOCK (connection);
02667 #endif
02668
02669 if (last_unref)
02670 {
02671 #ifndef DBUS_DISABLE_CHECKS
02672 if (_dbus_transport_get_is_connected (connection->transport))
02673 {
02674 _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",
02675 connection->shareable ?
02676 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02677 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02678 return;
02679 }
02680 #endif
02681 _dbus_connection_last_unref (connection);
02682 }
02683 }
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694 static void
02695 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02696 {
02697 DBusDispatchStatus status;
02698
02699 HAVE_LOCK_CHECK (connection);
02700
02701 _dbus_verbose ("Disconnecting %p\n", connection);
02702
02703
02704
02705
02706
02707 _dbus_connection_ref_unlocked (connection);
02708
02709 _dbus_transport_disconnect (connection->transport);
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02721
02722
02723 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02724
02725
02726 dbus_connection_unref (connection);
02727 }
02728
02771 void
02772 dbus_connection_close (DBusConnection *connection)
02773 {
02774 _dbus_return_if_fail (connection != NULL);
02775 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02776
02777 CONNECTION_LOCK (connection);
02778
02779 #ifndef DBUS_DISABLE_CHECKS
02780 if (connection->shareable)
02781 {
02782 CONNECTION_UNLOCK (connection);
02783
02784 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02785 return;
02786 }
02787 #endif
02788
02789 _dbus_connection_close_possibly_shared_and_unlock (connection);
02790 }
02791
02792 static dbus_bool_t
02793 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02794 {
02795 HAVE_LOCK_CHECK (connection);
02796 return _dbus_transport_get_is_connected (connection->transport);
02797 }
02798
02812 dbus_bool_t
02813 dbus_connection_get_is_connected (DBusConnection *connection)
02814 {
02815 dbus_bool_t res;
02816
02817 _dbus_return_val_if_fail (connection != NULL, FALSE);
02818
02819 CONNECTION_LOCK (connection);
02820 res = _dbus_connection_get_is_connected_unlocked (connection);
02821 CONNECTION_UNLOCK (connection);
02822
02823 return res;
02824 }
02825
02834 dbus_bool_t
02835 dbus_connection_get_is_authenticated (DBusConnection *connection)
02836 {
02837 dbus_bool_t res;
02838
02839 _dbus_return_val_if_fail (connection != NULL, FALSE);
02840
02841 CONNECTION_LOCK (connection);
02842 res = _dbus_transport_get_is_authenticated (connection->transport);
02843 CONNECTION_UNLOCK (connection);
02844
02845 return res;
02846 }
02847
02868 dbus_bool_t
02869 dbus_connection_get_is_anonymous (DBusConnection *connection)
02870 {
02871 dbus_bool_t res;
02872
02873 _dbus_return_val_if_fail (connection != NULL, FALSE);
02874
02875 CONNECTION_LOCK (connection);
02876 res = _dbus_transport_get_is_anonymous (connection->transport);
02877 CONNECTION_UNLOCK (connection);
02878
02879 return res;
02880 }
02881
02913 char*
02914 dbus_connection_get_server_id (DBusConnection *connection)
02915 {
02916 char *id;
02917
02918 _dbus_return_val_if_fail (connection != NULL, FALSE);
02919
02920 CONNECTION_LOCK (connection);
02921 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02922 CONNECTION_UNLOCK (connection);
02923
02924 return id;
02925 }
02926
02940 void
02941 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02942 dbus_bool_t exit_on_disconnect)
02943 {
02944 _dbus_return_if_fail (connection != NULL);
02945
02946 CONNECTION_LOCK (connection);
02947 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02948 CONNECTION_UNLOCK (connection);
02949 }
02950
02960 DBusPreallocatedSend*
02961 dbus_connection_preallocate_send (DBusConnection *connection)
02962 {
02963 DBusPreallocatedSend *preallocated;
02964
02965 _dbus_return_val_if_fail (connection != NULL, NULL);
02966
02967 CONNECTION_LOCK (connection);
02968
02969 preallocated =
02970 _dbus_connection_preallocate_send_unlocked (connection);
02971
02972 CONNECTION_UNLOCK (connection);
02973
02974 return preallocated;
02975 }
02976
02986 void
02987 dbus_connection_free_preallocated_send (DBusConnection *connection,
02988 DBusPreallocatedSend *preallocated)
02989 {
02990 _dbus_return_if_fail (connection != NULL);
02991 _dbus_return_if_fail (preallocated != NULL);
02992 _dbus_return_if_fail (connection == preallocated->connection);
02993
02994 _dbus_list_free_link (preallocated->queue_link);
02995 _dbus_counter_unref (preallocated->counter_link->data);
02996 _dbus_list_free_link (preallocated->counter_link);
02997 dbus_free (preallocated);
02998 }
02999
03012 void
03013 dbus_connection_send_preallocated (DBusConnection *connection,
03014 DBusPreallocatedSend *preallocated,
03015 DBusMessage *message,
03016 dbus_uint32_t *client_serial)
03017 {
03018 _dbus_return_if_fail (connection != NULL);
03019 _dbus_return_if_fail (preallocated != NULL);
03020 _dbus_return_if_fail (message != NULL);
03021 _dbus_return_if_fail (preallocated->connection == connection);
03022 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03023 dbus_message_get_member (message) != NULL);
03024 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03025 (dbus_message_get_interface (message) != NULL &&
03026 dbus_message_get_member (message) != NULL));
03027
03028 CONNECTION_LOCK (connection);
03029 _dbus_connection_send_preallocated_and_unlock (connection,
03030 preallocated,
03031 message, client_serial);
03032 }
03033
03034 static dbus_bool_t
03035 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03036 DBusMessage *message,
03037 dbus_uint32_t *client_serial)
03038 {
03039 DBusPreallocatedSend *preallocated;
03040
03041 _dbus_assert (connection != NULL);
03042 _dbus_assert (message != NULL);
03043
03044 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03045 if (preallocated == NULL)
03046 return FALSE;
03047
03048 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03049 preallocated,
03050 message,
03051 client_serial);
03052 return TRUE;
03053 }
03054
03076 dbus_bool_t
03077 dbus_connection_send (DBusConnection *connection,
03078 DBusMessage *message,
03079 dbus_uint32_t *serial)
03080 {
03081 _dbus_return_val_if_fail (connection != NULL, FALSE);
03082 _dbus_return_val_if_fail (message != NULL, FALSE);
03083
03084 CONNECTION_LOCK (connection);
03085
03086 return _dbus_connection_send_and_unlock (connection,
03087 message,
03088 serial);
03089 }
03090
03091 static dbus_bool_t
03092 reply_handler_timeout (void *data)
03093 {
03094 DBusConnection *connection;
03095 DBusDispatchStatus status;
03096 DBusPendingCall *pending = data;
03097
03098 connection = _dbus_pending_call_get_connection_and_lock (pending);
03099
03100 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03101 connection);
03102 _dbus_connection_remove_timeout_unlocked (connection,
03103 _dbus_pending_call_get_timeout_unlocked (pending));
03104 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03105
03106 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03107 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03108
03109
03110 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03111
03112 return TRUE;
03113 }
03114
03152 dbus_bool_t
03153 dbus_connection_send_with_reply (DBusConnection *connection,
03154 DBusMessage *message,
03155 DBusPendingCall **pending_return,
03156 int timeout_milliseconds)
03157 {
03158 DBusPendingCall *pending;
03159 dbus_int32_t serial = -1;
03160 DBusDispatchStatus status;
03161
03162 _dbus_return_val_if_fail (connection != NULL, FALSE);
03163 _dbus_return_val_if_fail (message != NULL, FALSE);
03164 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03165
03166 if (pending_return)
03167 *pending_return = NULL;
03168
03169 CONNECTION_LOCK (connection);
03170
03171 if (!_dbus_connection_get_is_connected_unlocked (connection))
03172 {
03173 CONNECTION_UNLOCK (connection);
03174
03175 return TRUE;
03176 }
03177
03178 pending = _dbus_pending_call_new_unlocked (connection,
03179 timeout_milliseconds,
03180 reply_handler_timeout);
03181
03182 if (pending == NULL)
03183 {
03184 CONNECTION_UNLOCK (connection);
03185 return FALSE;
03186 }
03187
03188
03189 serial = dbus_message_get_serial (message);
03190 if (serial == 0)
03191 {
03192 serial = _dbus_connection_get_next_client_serial (connection);
03193 _dbus_message_set_serial (message, serial);
03194 }
03195
03196 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03197 goto error;
03198
03199
03200
03201
03202
03203 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03204 pending))
03205 goto error;
03206
03207 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03208 {
03209 _dbus_connection_detach_pending_call_and_unlock (connection,
03210 pending);
03211 goto error_unlocked;
03212 }
03213
03214 if (pending_return)
03215 *pending_return = pending;
03216 else
03217 {
03218 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03219
03220
03221
03222 }
03223
03224 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03225
03226
03227 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03228
03229 if (pending_return == NULL)
03230 dbus_pending_call_unref (pending);
03231
03232 return TRUE;
03233
03234 error:
03235 CONNECTION_UNLOCK (connection);
03236 error_unlocked:
03237 dbus_pending_call_unref (pending);
03238 return FALSE;
03239 }
03240
03271 DBusMessage*
03272 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03273 DBusMessage *message,
03274 int timeout_milliseconds,
03275 DBusError *error)
03276 {
03277 DBusMessage *reply;
03278 DBusPendingCall *pending;
03279
03280 _dbus_return_val_if_fail (connection != NULL, NULL);
03281 _dbus_return_val_if_fail (message != NULL, NULL);
03282 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03283 _dbus_return_val_if_error_is_set (error, NULL);
03284
03285 if (!dbus_connection_send_with_reply (connection, message,
03286 &pending, timeout_milliseconds))
03287 {
03288 _DBUS_SET_OOM (error);
03289 return NULL;
03290 }
03291
03292 if (pending == NULL)
03293 {
03294 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03295 return NULL;
03296 }
03297
03298 dbus_pending_call_block (pending);
03299
03300 reply = dbus_pending_call_steal_reply (pending);
03301 if (_dbus_pending_get_error (pending) != 0) {
03302 char message[NEXENTA_ERROR_MAX_LENGTH];
03303 sprintf (message, "%s%d", NEXENTA_ERROR_PREFIX, _dbus_pending_get_error (pending));
03304 dbus_set_error (error, DBUS_ERROR_NEXENTA_AUTH, message);
03305 dbus_pending_call_unref (pending);
03306 if (reply)
03307 dbus_message_unref (reply);
03308 return NULL;
03309 };
03310 dbus_pending_call_unref (pending);
03311
03312
03313
03314
03315 _dbus_assert (reply != NULL);
03316
03317 if (dbus_set_error_from_message (error, reply))
03318 {
03319 dbus_message_unref (reply);
03320 return NULL;
03321 }
03322 else
03323 return reply;
03324 }
03325
03334 DBusDispatchStatus
03335 _dbus_connection_flush_unlocked (DBusConnection *connection)
03336 {
03337
03338
03339
03340
03341
03342 DBusDispatchStatus status;
03343
03344 HAVE_LOCK_CHECK (connection);
03345
03346 while (connection->n_outgoing > 0 &&
03347 _dbus_connection_get_is_connected_unlocked (connection))
03348 {
03349 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03350 HAVE_LOCK_CHECK (connection);
03351 _dbus_connection_do_iteration_unlocked (connection,
03352 DBUS_ITERATION_DO_READING |
03353 DBUS_ITERATION_DO_WRITING |
03354 DBUS_ITERATION_BLOCK,
03355 -1);
03356 }
03357
03358 HAVE_LOCK_CHECK (connection);
03359 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03360 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03361
03362 HAVE_LOCK_CHECK (connection);
03363 return status;
03364 }
03365
03371 void
03372 dbus_connection_flush (DBusConnection *connection)
03373 {
03374
03375
03376
03377
03378
03379 DBusDispatchStatus status;
03380
03381 _dbus_return_if_fail (connection != NULL);
03382
03383 CONNECTION_LOCK (connection);
03384
03385 status = _dbus_connection_flush_unlocked (connection);
03386
03387 HAVE_LOCK_CHECK (connection);
03388
03389 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03390
03391 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03392 }
03393
03404 static dbus_bool_t
03405 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03406 int timeout_milliseconds,
03407 dbus_bool_t dispatch)
03408 {
03409 DBusDispatchStatus dstatus;
03410 dbus_bool_t no_progress_possible;
03411
03412 dstatus = dbus_connection_get_dispatch_status (connection);
03413
03414 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03415 {
03416 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03417 dbus_connection_dispatch (connection);
03418 CONNECTION_LOCK (connection);
03419 }
03420 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03421 {
03422 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03423 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03424 CONNECTION_LOCK (connection);
03425 }
03426 else
03427 {
03428 CONNECTION_LOCK (connection);
03429 if (_dbus_connection_get_is_connected_unlocked (connection))
03430 {
03431 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03432 _dbus_connection_do_iteration_unlocked (connection,
03433 DBUS_ITERATION_DO_READING |
03434 DBUS_ITERATION_DO_WRITING |
03435 DBUS_ITERATION_BLOCK,
03436 timeout_milliseconds);
03437 }
03438 }
03439
03440 HAVE_LOCK_CHECK (connection);
03441
03442
03443
03444
03445 if (dispatch)
03446 no_progress_possible = connection->n_incoming == 0 &&
03447 connection->disconnect_message_link == NULL;
03448 else
03449 no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03450 CONNECTION_UNLOCK (connection);
03451 return !no_progress_possible;
03452 }
03453
03454
03489 dbus_bool_t
03490 dbus_connection_read_write_dispatch (DBusConnection *connection,
03491 int timeout_milliseconds)
03492 {
03493 _dbus_return_val_if_fail (connection != NULL, FALSE);
03494 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03495 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03496 }
03497
03521 dbus_bool_t
03522 dbus_connection_read_write (DBusConnection *connection,
03523 int timeout_milliseconds)
03524 {
03525 _dbus_return_val_if_fail (connection != NULL, FALSE);
03526 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03527 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03528 }
03529
03530
03531
03532
03533
03534
03535 static void
03536 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03537 DBusMessage *head_of_queue)
03538 {
03539 HAVE_LOCK_CHECK (connection);
03540
03541
03542 if (connection->disconnect_message_link == NULL &&
03543 dbus_message_is_signal (head_of_queue,
03544 DBUS_INTERFACE_LOCAL,
03545 "Disconnected"))
03546 {
03547 connection->disconnected_message_arrived = TRUE;
03548 }
03549 }
03550
03570 DBusMessage*
03571 dbus_connection_borrow_message (DBusConnection *connection)
03572 {
03573 DBusDispatchStatus status;
03574 DBusMessage *message;
03575
03576 _dbus_return_val_if_fail (connection != NULL, NULL);
03577
03578 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03579
03580
03581
03582
03583 status = dbus_connection_get_dispatch_status (connection);
03584 if (status != DBUS_DISPATCH_DATA_REMAINS)
03585 return NULL;
03586
03587 CONNECTION_LOCK (connection);
03588
03589 _dbus_connection_acquire_dispatch (connection);
03590
03591
03592 _dbus_assert (connection->message_borrowed == NULL);
03593
03594 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03595
03596 message = connection->message_borrowed;
03597
03598 check_disconnected_message_arrived_unlocked (connection, message);
03599
03600
03601 if (message == NULL)
03602 _dbus_connection_release_dispatch (connection);
03603
03604 CONNECTION_UNLOCK (connection);
03605
03606
03607
03608 return message;
03609 }
03610
03619 void
03620 dbus_connection_return_message (DBusConnection *connection,
03621 DBusMessage *message)
03622 {
03623 DBusDispatchStatus status;
03624
03625 _dbus_return_if_fail (connection != NULL);
03626 _dbus_return_if_fail (message != NULL);
03627 _dbus_return_if_fail (message == connection->message_borrowed);
03628 _dbus_return_if_fail (connection->dispatch_acquired);
03629
03630 CONNECTION_LOCK (connection);
03631
03632 _dbus_assert (message == connection->message_borrowed);
03633
03634 connection->message_borrowed = NULL;
03635
03636 _dbus_connection_release_dispatch (connection);
03637
03638 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03639 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03640 }
03641
03651 void
03652 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03653 DBusMessage *message)
03654 {
03655 DBusMessage *pop_message;
03656 DBusDispatchStatus status;
03657
03658 _dbus_return_if_fail (connection != NULL);
03659 _dbus_return_if_fail (message != NULL);
03660 _dbus_return_if_fail (message == connection->message_borrowed);
03661 _dbus_return_if_fail (connection->dispatch_acquired);
03662
03663 CONNECTION_LOCK (connection);
03664
03665 _dbus_assert (message == connection->message_borrowed);
03666
03667 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03668 _dbus_assert (message == pop_message);
03669
03670 connection->n_incoming -= 1;
03671
03672 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03673 message, connection->n_incoming);
03674
03675 connection->message_borrowed = NULL;
03676
03677 _dbus_connection_release_dispatch (connection);
03678
03679 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03680 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03681 }
03682
03683
03684
03685
03686 static DBusList*
03687 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03688 {
03689 HAVE_LOCK_CHECK (connection);
03690
03691 _dbus_assert (connection->message_borrowed == NULL);
03692
03693 if (connection->n_incoming > 0)
03694 {
03695 DBusList *link;
03696
03697 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03698 connection->n_incoming -= 1;
03699
03700 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03701 link->data,
03702 dbus_message_get_type (link->data),
03703 dbus_message_get_path (link->data) ?
03704 dbus_message_get_path (link->data) :
03705 "no path",
03706 dbus_message_get_interface (link->data) ?
03707 dbus_message_get_interface (link->data) :
03708 "no interface",
03709 dbus_message_get_member (link->data) ?
03710 dbus_message_get_member (link->data) :
03711 "no member",
03712 dbus_message_get_signature (link->data),
03713 connection, connection->n_incoming);
03714
03715 check_disconnected_message_arrived_unlocked (connection, link->data);
03716
03717 return link;
03718 }
03719 else
03720 return NULL;
03721 }
03722
03723
03724
03725
03726 static DBusMessage*
03727 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03728 {
03729 DBusList *link;
03730
03731 HAVE_LOCK_CHECK (connection);
03732
03733 link = _dbus_connection_pop_message_link_unlocked (connection);
03734
03735 if (link != NULL)
03736 {
03737 DBusMessage *message;
03738
03739 message = link->data;
03740
03741 _dbus_list_free_link (link);
03742
03743 return message;
03744 }
03745 else
03746 return NULL;
03747 }
03748
03749 static void
03750 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03751 DBusList *message_link)
03752 {
03753 HAVE_LOCK_CHECK (connection);
03754
03755 _dbus_assert (message_link != NULL);
03756
03757 _dbus_assert (connection->message_borrowed == NULL);
03758
03759 _dbus_assert (connection->dispatch_acquired);
03760
03761 _dbus_list_prepend_link (&connection->incoming_messages,
03762 message_link);
03763 connection->n_incoming += 1;
03764
03765 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03766 message_link->data,
03767 dbus_message_get_type (message_link->data),
03768 dbus_message_get_interface (message_link->data) ?
03769 dbus_message_get_interface (message_link->data) :
03770 "no interface",
03771 dbus_message_get_member (message_link->data) ?
03772 dbus_message_get_member (message_link->data) :
03773 "no member",
03774 dbus_message_get_signature (message_link->data),
03775 connection, connection->n_incoming);
03776 }
03777
03797 DBusMessage*
03798 dbus_connection_pop_message (DBusConnection *connection)
03799 {
03800 DBusMessage *message;
03801 DBusDispatchStatus status;
03802
03803 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03804
03805
03806
03807
03808 status = dbus_connection_get_dispatch_status (connection);
03809 if (status != DBUS_DISPATCH_DATA_REMAINS)
03810 return NULL;
03811
03812 CONNECTION_LOCK (connection);
03813 _dbus_connection_acquire_dispatch (connection);
03814 HAVE_LOCK_CHECK (connection);
03815
03816 message = _dbus_connection_pop_message_unlocked (connection);
03817
03818 _dbus_verbose ("Returning popped message %p\n", message);
03819
03820 _dbus_connection_release_dispatch (connection);
03821
03822 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03823 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03824
03825 return message;
03826 }
03827
03835 static void
03836 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03837 {
03838 HAVE_LOCK_CHECK (connection);
03839
03840 _dbus_connection_ref_unlocked (connection);
03841 CONNECTION_UNLOCK (connection);
03842
03843 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03844 _dbus_mutex_lock (connection->dispatch_mutex);
03845
03846 while (connection->dispatch_acquired)
03847 {
03848 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03849 _dbus_condvar_wait (connection->dispatch_cond,
03850 connection->dispatch_mutex);
03851 }
03852
03853 _dbus_assert (!connection->dispatch_acquired);
03854
03855 connection->dispatch_acquired = TRUE;
03856
03857 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03858 _dbus_mutex_unlock (connection->dispatch_mutex);
03859
03860 CONNECTION_LOCK (connection);
03861 _dbus_connection_unref_unlocked (connection);
03862 }
03863
03871 static void
03872 _dbus_connection_release_dispatch (DBusConnection *connection)
03873 {
03874 HAVE_LOCK_CHECK (connection);
03875
03876 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03877 _dbus_mutex_lock (connection->dispatch_mutex);
03878
03879 _dbus_assert (connection->dispatch_acquired);
03880
03881 connection->dispatch_acquired = FALSE;
03882 _dbus_condvar_wake_one (connection->dispatch_cond);
03883
03884 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03885 _dbus_mutex_unlock (connection->dispatch_mutex);
03886 }
03887
03888 static void
03889 _dbus_connection_failed_pop (DBusConnection *connection,
03890 DBusList *message_link)
03891 {
03892 _dbus_list_prepend_link (&connection->incoming_messages,
03893 message_link);
03894 connection->n_incoming += 1;
03895 }
03896
03897
03898 static void
03899 notify_disconnected_unlocked (DBusConnection *connection)
03900 {
03901 HAVE_LOCK_CHECK (connection);
03902
03903
03904
03905
03906
03907
03908
03909 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03910
03911
03912
03913
03914
03915 if (connection->n_outgoing > 0)
03916 {
03917 DBusList *link;
03918
03919 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03920 connection->n_outgoing);
03921
03922 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03923 {
03924 _dbus_connection_message_sent (connection, link->data);
03925 }
03926 }
03927 }
03928
03929
03930 static DBusDispatchStatus
03931 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03932 {
03933 HAVE_LOCK_CHECK (connection);
03934
03935 if (connection->disconnect_message_link != NULL)
03936 {
03937 _dbus_verbose ("Sending disconnect message from %s\n",
03938 _DBUS_FUNCTION_NAME);
03939
03940
03941
03942
03943 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03944
03945
03946
03947
03948 _dbus_connection_queue_synthesized_message_link (connection,
03949 connection->disconnect_message_link);
03950 connection->disconnect_message_link = NULL;
03951
03952 return DBUS_DISPATCH_DATA_REMAINS;
03953 }
03954
03955 return DBUS_DISPATCH_COMPLETE;
03956 }
03957
03958 static DBusDispatchStatus
03959 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03960 {
03961 HAVE_LOCK_CHECK (connection);
03962
03963 if (connection->n_incoming > 0)
03964 return DBUS_DISPATCH_DATA_REMAINS;
03965 else if (!_dbus_transport_queue_messages (connection->transport))
03966 return DBUS_DISPATCH_NEED_MEMORY;
03967 else
03968 {
03969 DBusDispatchStatus status;
03970 dbus_bool_t is_connected;
03971
03972 status = _dbus_transport_get_dispatch_status (connection->transport);
03973 is_connected = _dbus_transport_get_is_connected (connection->transport);
03974
03975 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03976 DISPATCH_STATUS_NAME (status), is_connected);
03977
03978 if (!is_connected)
03979 {
03980
03981
03982
03983
03984
03985
03986 notify_disconnected_unlocked (connection);
03987
03988
03989
03990
03991
03992
03993 if (status == DBUS_DISPATCH_COMPLETE)
03994 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03995 }
03996
03997 if (status != DBUS_DISPATCH_COMPLETE)
03998 return status;
03999 else if (connection->n_incoming > 0)
04000 return DBUS_DISPATCH_DATA_REMAINS;
04001 else
04002 return DBUS_DISPATCH_COMPLETE;
04003 }
04004 }
04005
04006 static void
04007 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04008 DBusDispatchStatus new_status)
04009 {
04010 dbus_bool_t changed;
04011 DBusDispatchStatusFunction function;
04012 void *data;
04013
04014 HAVE_LOCK_CHECK (connection);
04015
04016 _dbus_connection_ref_unlocked (connection);
04017
04018 changed = new_status != connection->last_dispatch_status;
04019
04020 connection->last_dispatch_status = new_status;
04021
04022 function = connection->dispatch_status_function;
04023 data = connection->dispatch_status_data;
04024
04025 if (connection->disconnected_message_arrived &&
04026 !connection->disconnected_message_processed)
04027 {
04028 connection->disconnected_message_processed = TRUE;
04029
04030
04031
04032
04033
04034 connection_forget_shared_unlocked (connection);
04035
04036 if (connection->exit_on_disconnect)
04037 {
04038 CONNECTION_UNLOCK (connection);
04039
04040 _dbus_verbose ("Exiting on Disconnected signal\n");
04041 _dbus_exit (1);
04042 _dbus_assert_not_reached ("Call to exit() returned");
04043 }
04044 }
04045
04046
04047 CONNECTION_UNLOCK (connection);
04048
04049 if (changed && function)
04050 {
04051 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04052 connection, new_status,
04053 DISPATCH_STATUS_NAME (new_status));
04054 (* function) (connection, new_status, data);
04055 }
04056
04057 dbus_connection_unref (connection);
04058 }
04059
04085 DBusDispatchStatus
04086 dbus_connection_get_dispatch_status (DBusConnection *connection)
04087 {
04088 DBusDispatchStatus status;
04089
04090 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04091
04092 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04093
04094 CONNECTION_LOCK (connection);
04095
04096 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04097
04098 CONNECTION_UNLOCK (connection);
04099
04100 return status;
04101 }
04102
04106 static DBusHandlerResult
04107 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04108 DBusMessage *message)
04109 {
04110 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04111 {
04112
04113 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04114 }
04115 else if (dbus_message_is_method_call (message,
04116 DBUS_INTERFACE_PEER,
04117 "Ping"))
04118 {
04119 DBusMessage *ret;
04120 dbus_bool_t sent;
04121
04122 ret = dbus_message_new_method_return (message);
04123 if (ret == NULL)
04124 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04125
04126 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04127
04128 dbus_message_unref (ret);
04129
04130 if (!sent)
04131 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04132
04133 return DBUS_HANDLER_RESULT_HANDLED;
04134 }
04135 else if (dbus_message_is_method_call (message,
04136 DBUS_INTERFACE_PEER,
04137 "GetMachineId"))
04138 {
04139 DBusMessage *ret;
04140 dbus_bool_t sent;
04141 DBusString uuid;
04142
04143 ret = dbus_message_new_method_return (message);
04144 if (ret == NULL)
04145 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04146
04147 sent = FALSE;
04148 _dbus_string_init (&uuid);
04149 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04150 {
04151 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04152 if (dbus_message_append_args (ret,
04153 DBUS_TYPE_STRING, &v_STRING,
04154 DBUS_TYPE_INVALID))
04155 {
04156 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04157 }
04158 }
04159 _dbus_string_free (&uuid);
04160
04161 dbus_message_unref (ret);
04162
04163 if (!sent)
04164 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04165
04166 return DBUS_HANDLER_RESULT_HANDLED;
04167 }
04168 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04169 {
04170
04171
04172
04173
04174
04175 DBusMessage *ret;
04176 dbus_bool_t sent;
04177
04178 ret = dbus_message_new_error (message,
04179 DBUS_ERROR_UNKNOWN_METHOD,
04180 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04181 if (ret == NULL)
04182 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04183
04184 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04185
04186 dbus_message_unref (ret);
04187
04188 if (!sent)
04189 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04190
04191 return DBUS_HANDLER_RESULT_HANDLED;
04192 }
04193 else
04194 {
04195 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04196 }
04197 }
04198
04205 static DBusHandlerResult
04206 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04207 DBusMessage *message)
04208 {
04209
04210
04211
04212 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04213 }
04214
04257 DBusDispatchStatus
04258 dbus_connection_dispatch (DBusConnection *connection)
04259 {
04260 DBusMessage *message;
04261 DBusList *link, *filter_list_copy, *message_link;
04262 DBusHandlerResult result;
04263 DBusPendingCall *pending;
04264 dbus_int32_t reply_serial;
04265 DBusDispatchStatus status;
04266
04267 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04268
04269 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04270
04271 CONNECTION_LOCK (connection);
04272 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04273 if (status != DBUS_DISPATCH_DATA_REMAINS)
04274 {
04275
04276 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04277 return status;
04278 }
04279
04280
04281
04282
04283 _dbus_connection_ref_unlocked (connection);
04284
04285 _dbus_connection_acquire_dispatch (connection);
04286 HAVE_LOCK_CHECK (connection);
04287
04288 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04289 if (message_link == NULL)
04290 {
04291
04292
04293 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04294
04295 _dbus_connection_release_dispatch (connection);
04296
04297 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04298
04299 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04300
04301 dbus_connection_unref (connection);
04302
04303 return status;
04304 }
04305
04306 message = message_link->data;
04307
04308 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04309 message,
04310 dbus_message_get_type (message),
04311 dbus_message_get_interface (message) ?
04312 dbus_message_get_interface (message) :
04313 "no interface",
04314 dbus_message_get_member (message) ?
04315 dbus_message_get_member (message) :
04316 "no member",
04317 dbus_message_get_signature (message));
04318
04319 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04320
04321
04322
04323
04324
04325
04326
04327
04328 reply_serial = dbus_message_get_reply_serial (message);
04329 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04330 reply_serial);
04331 if (pending)
04332 {
04333 _dbus_verbose ("Dispatching a pending reply\n");
04334 complete_pending_call_and_unlock (connection, pending, message);
04335 pending = NULL;
04336
04337 CONNECTION_LOCK (connection);
04338 _dbus_verbose ("pending call completed in dispatch\n");
04339 result = DBUS_HANDLER_RESULT_HANDLED;
04340 goto out;
04341 }
04342
04343 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04344 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04345 goto out;
04346
04347 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04348 {
04349 _dbus_connection_release_dispatch (connection);
04350 HAVE_LOCK_CHECK (connection);
04351
04352 _dbus_connection_failed_pop (connection, message_link);
04353
04354
04355 _dbus_connection_update_dispatch_status_and_unlock (connection,
04356 DBUS_DISPATCH_NEED_MEMORY);
04357
04358 if (pending)
04359 dbus_pending_call_unref (pending);
04360 dbus_connection_unref (connection);
04361
04362 return DBUS_DISPATCH_NEED_MEMORY;
04363 }
04364
04365 _dbus_list_foreach (&filter_list_copy,
04366 (DBusForeachFunction)_dbus_message_filter_ref,
04367 NULL);
04368
04369
04370
04371
04372 CONNECTION_UNLOCK (connection);
04373
04374 link = _dbus_list_get_first_link (&filter_list_copy);
04375 while (link != NULL)
04376 {
04377 DBusMessageFilter *filter = link->data;
04378 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04379
04380 if (filter->function == NULL)
04381 {
04382 _dbus_verbose (" filter was removed in a callback function\n");
04383 link = next;
04384 continue;
04385 }
04386
04387 _dbus_verbose (" running filter on message %p\n", message);
04388 result = (* filter->function) (connection, message, filter->user_data);
04389
04390 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04391 break;
04392
04393 link = next;
04394 }
04395
04396 _dbus_list_foreach (&filter_list_copy,
04397 (DBusForeachFunction)_dbus_message_filter_unref,
04398 NULL);
04399 _dbus_list_clear (&filter_list_copy);
04400
04401 CONNECTION_LOCK (connection);
04402
04403 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04404 {
04405 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04406 goto out;
04407 }
04408 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04409 {
04410 _dbus_verbose ("filter handled message in dispatch\n");
04411 goto out;
04412 }
04413
04414
04415
04416
04417 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
04418 message,
04419 dbus_message_get_type (message),
04420 dbus_message_get_interface (message) ?
04421 dbus_message_get_interface (message) :
04422 "no interface",
04423 dbus_message_get_member (message) ?
04424 dbus_message_get_member (message) :
04425 "no member",
04426 dbus_message_get_signature (message));
04427
04428 HAVE_LOCK_CHECK (connection);
04429 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04430 message);
04431
04432 CONNECTION_LOCK (connection);
04433
04434 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04435 {
04436 _dbus_verbose ("object tree handled message in dispatch\n");
04437 goto out;
04438 }
04439
04440 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04441 {
04442 DBusMessage *reply;
04443 DBusString str;
04444 DBusPreallocatedSend *preallocated;
04445
04446 _dbus_verbose (" sending error %s\n",
04447 DBUS_ERROR_UNKNOWN_METHOD);
04448
04449 if (!_dbus_string_init (&str))
04450 {
04451 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04452 _dbus_verbose ("no memory for error string in dispatch\n");
04453 goto out;
04454 }
04455
04456 if (!_dbus_string_append_printf (&str,
04457 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04458 dbus_message_get_member (message),
04459 dbus_message_get_signature (message),
04460 dbus_message_get_interface (message)))
04461 {
04462 _dbus_string_free (&str);
04463 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04464 _dbus_verbose ("no memory for error string in dispatch\n");
04465 goto out;
04466 }
04467
04468 reply = dbus_message_new_error (message,
04469 DBUS_ERROR_UNKNOWN_METHOD,
04470 _dbus_string_get_const_data (&str));
04471 _dbus_string_free (&str);
04472
04473 if (reply == NULL)
04474 {
04475 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04476 _dbus_verbose ("no memory for error reply in dispatch\n");
04477 goto out;
04478 }
04479
04480 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04481
04482 if (preallocated == NULL)
04483 {
04484 dbus_message_unref (reply);
04485 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04486 _dbus_verbose ("no memory for error send in dispatch\n");
04487 goto out;
04488 }
04489
04490 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04491 reply, NULL);
04492
04493 dbus_message_unref (reply);
04494
04495 result = DBUS_HANDLER_RESULT_HANDLED;
04496 }
04497
04498 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04499 dbus_message_get_type (message),
04500 dbus_message_get_interface (message) ?
04501 dbus_message_get_interface (message) :
04502 "no interface",
04503 dbus_message_get_member (message) ?
04504 dbus_message_get_member (message) :
04505 "no member",
04506 dbus_message_get_signature (message),
04507 connection);
04508
04509 out:
04510 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04511 {
04512 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04513
04514
04515
04516
04517
04518 _dbus_connection_putback_message_link_unlocked (connection,
04519 message_link);
04520 }
04521 else
04522 {
04523 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04524
04525 _dbus_list_free_link (message_link);
04526 dbus_message_unref (message);
04527
04528
04529 }
04530
04531 _dbus_connection_release_dispatch (connection);
04532 HAVE_LOCK_CHECK (connection);
04533
04534 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04535 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04536
04537
04538 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04539
04540 dbus_connection_unref (connection);
04541
04542 return status;
04543 }
04544
04604 dbus_bool_t
04605 dbus_connection_set_watch_functions (DBusConnection *connection,
04606 DBusAddWatchFunction add_function,
04607 DBusRemoveWatchFunction remove_function,
04608 DBusWatchToggledFunction toggled_function,
04609 void *data,
04610 DBusFreeFunction free_data_function)
04611 {
04612 dbus_bool_t retval;
04613 DBusWatchList *watches;
04614
04615 _dbus_return_val_if_fail (connection != NULL, FALSE);
04616
04617 CONNECTION_LOCK (connection);
04618
04619 #ifndef DBUS_DISABLE_CHECKS
04620 if (connection->watches == NULL)
04621 {
04622 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04623 _DBUS_FUNCTION_NAME);
04624 return FALSE;
04625 }
04626 #endif
04627
04628
04629 _dbus_connection_ref_unlocked (connection);
04630
04631
04632
04633
04634
04635 watches = connection->watches;
04636 connection->watches = NULL;
04637 CONNECTION_UNLOCK (connection);
04638
04639 retval = _dbus_watch_list_set_functions (watches,
04640 add_function, remove_function,
04641 toggled_function,
04642 data, free_data_function);
04643 CONNECTION_LOCK (connection);
04644 connection->watches = watches;
04645
04646 CONNECTION_UNLOCK (connection);
04647
04648 dbus_connection_unref (connection);
04649
04650 return retval;
04651 }
04652
04686 dbus_bool_t
04687 dbus_connection_set_timeout_functions (DBusConnection *connection,
04688 DBusAddTimeoutFunction add_function,
04689 DBusRemoveTimeoutFunction remove_function,
04690 DBusTimeoutToggledFunction toggled_function,
04691 void *data,
04692 DBusFreeFunction free_data_function)
04693 {
04694 dbus_bool_t retval;
04695 DBusTimeoutList *timeouts;
04696
04697 _dbus_return_val_if_fail (connection != NULL, FALSE);
04698
04699 CONNECTION_LOCK (connection);
04700
04701 #ifndef DBUS_DISABLE_CHECKS
04702 if (connection->timeouts == NULL)
04703 {
04704 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04705 _DBUS_FUNCTION_NAME);
04706 return FALSE;
04707 }
04708 #endif
04709
04710
04711 _dbus_connection_ref_unlocked (connection);
04712
04713 timeouts = connection->timeouts;
04714 connection->timeouts = NULL;
04715 CONNECTION_UNLOCK (connection);
04716
04717 retval = _dbus_timeout_list_set_functions (timeouts,
04718 add_function, remove_function,
04719 toggled_function,
04720 data, free_data_function);
04721 CONNECTION_LOCK (connection);
04722 connection->timeouts = timeouts;
04723
04724 CONNECTION_UNLOCK (connection);
04725
04726 dbus_connection_unref (connection);
04727
04728 return retval;
04729 }
04730
04745 void
04746 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04747 DBusWakeupMainFunction wakeup_main_function,
04748 void *data,
04749 DBusFreeFunction free_data_function)
04750 {
04751 void *old_data;
04752 DBusFreeFunction old_free_data;
04753
04754 _dbus_return_if_fail (connection != NULL);
04755
04756 CONNECTION_LOCK (connection);
04757 old_data = connection->wakeup_main_data;
04758 old_free_data = connection->free_wakeup_main_data;
04759
04760 connection->wakeup_main_function = wakeup_main_function;
04761 connection->wakeup_main_data = data;
04762 connection->free_wakeup_main_data = free_data_function;
04763
04764 CONNECTION_UNLOCK (connection);
04765
04766
04767 if (old_free_data)
04768 (*old_free_data) (old_data);
04769 }
04770
04791 void
04792 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04793 DBusDispatchStatusFunction function,
04794 void *data,
04795 DBusFreeFunction free_data_function)
04796 {
04797 void *old_data;
04798 DBusFreeFunction old_free_data;
04799
04800 _dbus_return_if_fail (connection != NULL);
04801
04802 CONNECTION_LOCK (connection);
04803 old_data = connection->dispatch_status_data;
04804 old_free_data = connection->free_dispatch_status_data;
04805
04806 connection->dispatch_status_function = function;
04807 connection->dispatch_status_data = data;
04808 connection->free_dispatch_status_data = free_data_function;
04809
04810 CONNECTION_UNLOCK (connection);
04811
04812
04813 if (old_free_data)
04814 (*old_free_data) (old_data);
04815 }
04816
04836 dbus_bool_t
04837 dbus_connection_get_unix_fd (DBusConnection *connection,
04838 int *fd)
04839 {
04840 _dbus_return_val_if_fail (connection != NULL, FALSE);
04841 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04842
04843 #ifdef DBUS_WIN
04844
04845 return FALSE;
04846 #endif
04847
04848 return dbus_connection_get_socket(connection, fd);
04849 }
04850
04866 dbus_bool_t
04867 dbus_connection_get_socket(DBusConnection *connection,
04868 int *fd)
04869 {
04870 dbus_bool_t retval;
04871
04872 _dbus_return_val_if_fail (connection != NULL, FALSE);
04873 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04874
04875 CONNECTION_LOCK (connection);
04876
04877 retval = _dbus_transport_get_socket_fd (connection->transport,
04878 fd);
04879
04880 CONNECTION_UNLOCK (connection);
04881
04882 return retval;
04883 }
04884
04885
04908 dbus_bool_t
04909 dbus_connection_get_unix_user (DBusConnection *connection,
04910 unsigned long *uid)
04911 {
04912 dbus_bool_t result;
04913
04914 _dbus_return_val_if_fail (connection != NULL, FALSE);
04915 _dbus_return_val_if_fail (uid != NULL, FALSE);
04916
04917 CONNECTION_LOCK (connection);
04918
04919 if (!_dbus_transport_get_is_authenticated (connection->transport))
04920 result = FALSE;
04921 else
04922 result = _dbus_transport_get_unix_user (connection->transport,
04923 uid);
04924
04925 #ifdef DBUS_WIN
04926 _dbus_assert (!result);
04927 #endif
04928
04929 CONNECTION_UNLOCK (connection);
04930
04931 return result;
04932 }
04933
04944 dbus_bool_t
04945 dbus_connection_get_unix_process_id (DBusConnection *connection,
04946 unsigned long *pid)
04947 {
04948 dbus_bool_t result;
04949
04950 _dbus_return_val_if_fail (connection != NULL, FALSE);
04951 _dbus_return_val_if_fail (pid != NULL, FALSE);
04952
04953 CONNECTION_LOCK (connection);
04954
04955 if (!_dbus_transport_get_is_authenticated (connection->transport))
04956 result = FALSE;
04957 else
04958 result = _dbus_transport_get_unix_process_id (connection->transport,
04959 pid);
04960 #ifdef DBUS_WIN
04961 _dbus_assert (!result);
04962 #endif
04963
04964 CONNECTION_UNLOCK (connection);
04965
04966 return result;
04967 }
04968
04991 void
04992 dbus_connection_set_unix_user_function (DBusConnection *connection,
04993 DBusAllowUnixUserFunction function,
04994 void *data,
04995 DBusFreeFunction free_data_function)
04996 {
04997 void *old_data = NULL;
04998 DBusFreeFunction old_free_function = NULL;
04999
05000 _dbus_return_if_fail (connection != NULL);
05001
05002 CONNECTION_LOCK (connection);
05003 _dbus_transport_set_unix_user_function (connection->transport,
05004 function, data, free_data_function,
05005 &old_data, &old_free_function);
05006 CONNECTION_UNLOCK (connection);
05007
05008 if (old_free_function != NULL)
05009 (* old_free_function) (old_data);
05010 }
05011
05043 dbus_bool_t
05044 dbus_connection_get_windows_user (DBusConnection *connection,
05045 char **windows_sid_p)
05046 {
05047 dbus_bool_t result;
05048
05049 _dbus_return_val_if_fail (connection != NULL, FALSE);
05050 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05051
05052 CONNECTION_LOCK (connection);
05053
05054 if (!_dbus_transport_get_is_authenticated (connection->transport))
05055 result = FALSE;
05056 else
05057 result = _dbus_transport_get_windows_user (connection->transport,
05058 windows_sid_p);
05059
05060 #ifdef DBUS_UNIX
05061 _dbus_assert (!result);
05062 #endif
05063
05064 CONNECTION_UNLOCK (connection);
05065
05066 return result;
05067 }
05068
05090 void
05091 dbus_connection_set_windows_user_function (DBusConnection *connection,
05092 DBusAllowWindowsUserFunction function,
05093 void *data,
05094 DBusFreeFunction free_data_function)
05095 {
05096 void *old_data = NULL;
05097 DBusFreeFunction old_free_function = NULL;
05098
05099 _dbus_return_if_fail (connection != NULL);
05100
05101 CONNECTION_LOCK (connection);
05102 _dbus_transport_set_windows_user_function (connection->transport,
05103 function, data, free_data_function,
05104 &old_data, &old_free_function);
05105 CONNECTION_UNLOCK (connection);
05106
05107 if (old_free_function != NULL)
05108 (* old_free_function) (old_data);
05109 }
05110
05137 void
05138 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05139 dbus_bool_t value)
05140 {
05141 _dbus_return_if_fail (connection != NULL);
05142
05143 CONNECTION_LOCK (connection);
05144 _dbus_transport_set_allow_anonymous (connection->transport, value);
05145 CONNECTION_UNLOCK (connection);
05146 }
05147
05165 void
05166 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05167 dbus_bool_t value)
05168 {
05169 _dbus_return_if_fail (connection != NULL);
05170
05171 CONNECTION_LOCK (connection);
05172 connection->route_peer_messages = TRUE;
05173 CONNECTION_UNLOCK (connection);
05174 }
05175
05197 dbus_bool_t
05198 dbus_connection_add_filter (DBusConnection *connection,
05199 DBusHandleMessageFunction function,
05200 void *user_data,
05201 DBusFreeFunction free_data_function)
05202 {
05203 DBusMessageFilter *filter;
05204
05205 _dbus_return_val_if_fail (connection != NULL, FALSE);
05206 _dbus_return_val_if_fail (function != NULL, FALSE);
05207
05208 filter = dbus_new0 (DBusMessageFilter, 1);
05209 if (filter == NULL)
05210 return FALSE;
05211
05212 filter->refcount.value = 1;
05213
05214 CONNECTION_LOCK (connection);
05215
05216 if (!_dbus_list_append (&connection->filter_list,
05217 filter))
05218 {
05219 _dbus_message_filter_unref (filter);
05220 CONNECTION_UNLOCK (connection);
05221 return FALSE;
05222 }
05223
05224
05225
05226
05227
05228
05229 filter->function = function;
05230 filter->user_data = user_data;
05231 filter->free_user_data_function = free_data_function;
05232
05233 CONNECTION_UNLOCK (connection);
05234 return TRUE;
05235 }
05236
05249 void
05250 dbus_connection_remove_filter (DBusConnection *connection,
05251 DBusHandleMessageFunction function,
05252 void *user_data)
05253 {
05254 DBusList *link;
05255 DBusMessageFilter *filter;
05256
05257 _dbus_return_if_fail (connection != NULL);
05258 _dbus_return_if_fail (function != NULL);
05259
05260 CONNECTION_LOCK (connection);
05261
05262 filter = NULL;
05263
05264 link = _dbus_list_get_last_link (&connection->filter_list);
05265 while (link != NULL)
05266 {
05267 filter = link->data;
05268
05269 if (filter->function == function &&
05270 filter->user_data == user_data)
05271 {
05272 _dbus_list_remove_link (&connection->filter_list, link);
05273 filter->function = NULL;
05274
05275 break;
05276 }
05277
05278 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05279 }
05280
05281 CONNECTION_UNLOCK (connection);
05282
05283 #ifndef DBUS_DISABLE_CHECKS
05284 if (filter == NULL)
05285 {
05286 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05287 function, user_data);
05288 return;
05289 }
05290 #endif
05291
05292
05293 if (filter->free_user_data_function)
05294 (* filter->free_user_data_function) (filter->user_data);
05295
05296 filter->free_user_data_function = NULL;
05297 filter->user_data = NULL;
05298
05299 _dbus_message_filter_unref (filter);
05300 }
05301
05314 dbus_bool_t
05315 dbus_connection_try_register_object_path (DBusConnection *connection,
05316 const char *path,
05317 const DBusObjectPathVTable *vtable,
05318 void *user_data,
05319 DBusError *error)
05320 {
05321 char **decomposed_path;
05322 dbus_bool_t retval;
05323
05324 _dbus_return_val_if_fail (connection != NULL, FALSE);
05325 _dbus_return_val_if_fail (path != NULL, FALSE);
05326 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05327 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05328
05329 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05330 return FALSE;
05331
05332 CONNECTION_LOCK (connection);
05333
05334 retval = _dbus_object_tree_register (connection->objects,
05335 FALSE,
05336 (const char **) decomposed_path, vtable,
05337 user_data, error);
05338
05339 CONNECTION_UNLOCK (connection);
05340
05341 dbus_free_string_array (decomposed_path);
05342
05343 return retval;
05344 }
05345
05360 dbus_bool_t
05361 dbus_connection_register_object_path (DBusConnection *connection,
05362 const char *path,
05363 const DBusObjectPathVTable *vtable,
05364 void *user_data)
05365 {
05366 char **decomposed_path;
05367 dbus_bool_t retval;
05368 DBusError error = DBUS_ERROR_INIT;
05369
05370 _dbus_return_val_if_fail (connection != NULL, FALSE);
05371 _dbus_return_val_if_fail (path != NULL, FALSE);
05372 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05373 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05374
05375 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05376 return FALSE;
05377
05378 CONNECTION_LOCK (connection);
05379
05380 retval = _dbus_object_tree_register (connection->objects,
05381 FALSE,
05382 (const char **) decomposed_path, vtable,
05383 user_data, &error);
05384
05385 CONNECTION_UNLOCK (connection);
05386
05387 dbus_free_string_array (decomposed_path);
05388
05389 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05390 {
05391 _dbus_warn ("%s\n", error.message);
05392 dbus_error_free (&error);
05393 return FALSE;
05394 }
05395
05396 return retval;
05397 }
05398
05413 dbus_bool_t
05414 dbus_connection_try_register_fallback (DBusConnection *connection,
05415 const char *path,
05416 const DBusObjectPathVTable *vtable,
05417 void *user_data,
05418 DBusError *error)
05419 {
05420 char **decomposed_path;
05421 dbus_bool_t retval;
05422
05423 _dbus_return_val_if_fail (connection != NULL, FALSE);
05424 _dbus_return_val_if_fail (path != NULL, FALSE);
05425 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05426 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05427
05428 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05429 return FALSE;
05430
05431 CONNECTION_LOCK (connection);
05432
05433 retval = _dbus_object_tree_register (connection->objects,
05434 TRUE,
05435 (const char **) decomposed_path, vtable,
05436 user_data, error);
05437
05438 CONNECTION_UNLOCK (connection);
05439
05440 dbus_free_string_array (decomposed_path);
05441
05442 return retval;
05443 }
05444
05461 dbus_bool_t
05462 dbus_connection_register_fallback (DBusConnection *connection,
05463 const char *path,
05464 const DBusObjectPathVTable *vtable,
05465 void *user_data)
05466 {
05467 char **decomposed_path;
05468 dbus_bool_t retval;
05469 DBusError error = DBUS_ERROR_INIT;
05470
05471 _dbus_return_val_if_fail (connection != NULL, FALSE);
05472 _dbus_return_val_if_fail (path != NULL, FALSE);
05473 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05474 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05475
05476 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05477 return FALSE;
05478
05479 CONNECTION_LOCK (connection);
05480
05481 retval = _dbus_object_tree_register (connection->objects,
05482 TRUE,
05483 (const char **) decomposed_path, vtable,
05484 user_data, &error);
05485
05486 CONNECTION_UNLOCK (connection);
05487
05488 dbus_free_string_array (decomposed_path);
05489
05490 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05491 {
05492 _dbus_warn ("%s\n", error.message);
05493 dbus_error_free (&error);
05494 return FALSE;
05495 }
05496
05497 return retval;
05498 }
05499
05509 dbus_bool_t
05510 dbus_connection_unregister_object_path (DBusConnection *connection,
05511 const char *path)
05512 {
05513 char **decomposed_path;
05514
05515 _dbus_return_val_if_fail (connection != NULL, FALSE);
05516 _dbus_return_val_if_fail (path != NULL, FALSE);
05517 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05518
05519 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05520 return FALSE;
05521
05522 CONNECTION_LOCK (connection);
05523
05524 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05525
05526 dbus_free_string_array (decomposed_path);
05527
05528 return TRUE;
05529 }
05530
05541 dbus_bool_t
05542 dbus_connection_get_object_path_data (DBusConnection *connection,
05543 const char *path,
05544 void **data_p)
05545 {
05546 char **decomposed_path;
05547
05548 _dbus_return_val_if_fail (connection != NULL, FALSE);
05549 _dbus_return_val_if_fail (path != NULL, FALSE);
05550 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05551
05552 *data_p = NULL;
05553
05554 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05555 return FALSE;
05556
05557 CONNECTION_LOCK (connection);
05558
05559 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05560
05561 CONNECTION_UNLOCK (connection);
05562
05563 dbus_free_string_array (decomposed_path);
05564
05565 return TRUE;
05566 }
05567
05578 dbus_bool_t
05579 dbus_connection_list_registered (DBusConnection *connection,
05580 const char *parent_path,
05581 char ***child_entries)
05582 {
05583 char **decomposed_path;
05584 dbus_bool_t retval;
05585 _dbus_return_val_if_fail (connection != NULL, FALSE);
05586 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05587 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05588 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05589
05590 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05591 return FALSE;
05592
05593 CONNECTION_LOCK (connection);
05594
05595 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05596 (const char **) decomposed_path,
05597 child_entries);
05598 dbus_free_string_array (decomposed_path);
05599
05600 return retval;
05601 }
05602
05603 static DBusDataSlotAllocator slot_allocator;
05604 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05605
05620 dbus_bool_t
05621 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05622 {
05623 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05624 &_DBUS_LOCK_NAME (connection_slots),
05625 slot_p);
05626 }
05627
05639 void
05640 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05641 {
05642 _dbus_return_if_fail (*slot_p >= 0);
05643
05644 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05645 }
05646
05660 dbus_bool_t
05661 dbus_connection_set_data (DBusConnection *connection,
05662 dbus_int32_t slot,
05663 void *data,
05664 DBusFreeFunction free_data_func)
05665 {
05666 DBusFreeFunction old_free_func;
05667 void *old_data;
05668 dbus_bool_t retval;
05669
05670 _dbus_return_val_if_fail (connection != NULL, FALSE);
05671 _dbus_return_val_if_fail (slot >= 0, FALSE);
05672
05673 CONNECTION_LOCK (connection);
05674
05675 retval = _dbus_data_slot_list_set (&slot_allocator,
05676 &connection->slot_list,
05677 slot, data, free_data_func,
05678 &old_free_func, &old_data);
05679
05680 CONNECTION_UNLOCK (connection);
05681
05682 if (retval)
05683 {
05684
05685 if (old_free_func)
05686 (* old_free_func) (old_data);
05687 }
05688
05689 return retval;
05690 }
05691
05700 void*
05701 dbus_connection_get_data (DBusConnection *connection,
05702 dbus_int32_t slot)
05703 {
05704 void *res;
05705
05706 _dbus_return_val_if_fail (connection != NULL, NULL);
05707
05708 CONNECTION_LOCK (connection);
05709
05710 res = _dbus_data_slot_list_get (&slot_allocator,
05711 &connection->slot_list,
05712 slot);
05713
05714 CONNECTION_UNLOCK (connection);
05715
05716 return res;
05717 }
05718
05725 void
05726 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05727 {
05728 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05729 }
05730
05739 void
05740 dbus_connection_set_max_message_size (DBusConnection *connection,
05741 long size)
05742 {
05743 _dbus_return_if_fail (connection != NULL);
05744
05745 CONNECTION_LOCK (connection);
05746 _dbus_transport_set_max_message_size (connection->transport,
05747 size);
05748 CONNECTION_UNLOCK (connection);
05749 }
05750
05757 long
05758 dbus_connection_get_max_message_size (DBusConnection *connection)
05759 {
05760 long res;
05761
05762 _dbus_return_val_if_fail (connection != NULL, 0);
05763
05764 CONNECTION_LOCK (connection);
05765 res = _dbus_transport_get_max_message_size (connection->transport);
05766 CONNECTION_UNLOCK (connection);
05767 return res;
05768 }
05769
05795 void
05796 dbus_connection_set_max_received_size (DBusConnection *connection,
05797 long size)
05798 {
05799 _dbus_return_if_fail (connection != NULL);
05800
05801 CONNECTION_LOCK (connection);
05802 _dbus_transport_set_max_received_size (connection->transport,
05803 size);
05804 CONNECTION_UNLOCK (connection);
05805 }
05806
05813 long
05814 dbus_connection_get_max_received_size (DBusConnection *connection)
05815 {
05816 long res;
05817
05818 _dbus_return_val_if_fail (connection != NULL, 0);
05819
05820 CONNECTION_LOCK (connection);
05821 res = _dbus_transport_get_max_received_size (connection->transport);
05822 CONNECTION_UNLOCK (connection);
05823 return res;
05824 }
05825
05836 long
05837 dbus_connection_get_outgoing_size (DBusConnection *connection)
05838 {
05839 long res;
05840
05841 _dbus_return_val_if_fail (connection != NULL, 0);
05842
05843 CONNECTION_LOCK (connection);
05844 res = _dbus_counter_get_value (connection->outgoing_counter);
05845 CONNECTION_UNLOCK (connection);
05846 return res;
05847 }
05848
05849 int _dbus_connection_get_error (DBusConnection *connection)
05850 {
05851 return (connection)? _dbus_transport_get_error (connection->transport) : 0;
05852 }
05853