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 _DBUS_LOCK (shared_connections);
01675
01676 if (connection->server_guid != NULL)
01677 {
01678 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01679 connection->server_guid);
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 }
01688 else
01689 {
01690 _dbus_list_remove (&shared_connections_no_guid, connection);
01691 }
01692
01693 _DBUS_UNLOCK (shared_connections);
01694
01695
01696 _dbus_connection_unref_unlocked (connection);
01697 }
01698
01699 static DBusConnection*
01700 connection_try_from_address_entry (DBusAddressEntry *entry,
01701 DBusError *error)
01702 {
01703 DBusTransport *transport;
01704 DBusConnection *connection;
01705
01706 transport = _dbus_transport_open (entry, error);
01707
01708 if (transport == NULL)
01709 {
01710 _DBUS_ASSERT_ERROR_IS_SET (error);
01711 return NULL;
01712 }
01713
01714 connection = _dbus_connection_new_for_transport (transport);
01715
01716 _dbus_transport_unref (transport);
01717
01718 if (connection == NULL)
01719 {
01720 _DBUS_SET_OOM (error);
01721 return NULL;
01722 }
01723
01724 #ifndef DBUS_DISABLE_CHECKS
01725 _dbus_assert (!connection->have_connection_lock);
01726 #endif
01727 return connection;
01728 }
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 static DBusConnection*
01743 _dbus_connection_open_internal (const char *address,
01744 dbus_bool_t shared,
01745 DBusError *error)
01746 {
01747 DBusConnection *connection;
01748 DBusAddressEntry **entries;
01749 DBusError tmp_error = DBUS_ERROR_INIT;
01750 DBusError first_error = DBUS_ERROR_INIT;
01751 int len, i;
01752
01753 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01754
01755 _dbus_verbose ("opening %s connection to: %s\n",
01756 shared ? "shared" : "private", address);
01757
01758 if (!dbus_parse_address (address, &entries, &len, error))
01759 return NULL;
01760
01761 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01762
01763 connection = NULL;
01764
01765 for (i = 0; i < len; i++)
01766 {
01767 if (shared)
01768 {
01769 if (!connection_lookup_shared (entries[i], &connection))
01770 _DBUS_SET_OOM (&tmp_error);
01771 }
01772
01773 if (connection == NULL)
01774 {
01775 connection = connection_try_from_address_entry (entries[i],
01776 &tmp_error);
01777
01778 if (connection != NULL && shared)
01779 {
01780 const char *guid;
01781
01782 connection->shareable = TRUE;
01783
01784
01785 guid = dbus_address_entry_get_value (entries[i], "guid");
01786
01787 CONNECTION_LOCK (connection);
01788
01789 if (!connection_record_shared_unlocked (connection, guid))
01790 {
01791 _DBUS_SET_OOM (&tmp_error);
01792 _dbus_connection_close_possibly_shared_and_unlock (connection);
01793 dbus_connection_unref (connection);
01794 connection = NULL;
01795 }
01796 else
01797 CONNECTION_UNLOCK (connection);
01798 }
01799 }
01800
01801 if (connection)
01802 break;
01803
01804 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01805
01806 if (i == 0)
01807 dbus_move_error (&tmp_error, &first_error);
01808 else
01809 dbus_error_free (&tmp_error);
01810 }
01811
01812 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01813 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01814
01815 if (connection == NULL)
01816 {
01817 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01818 dbus_move_error (&first_error, error);
01819 }
01820 else
01821 dbus_error_free (&first_error);
01822
01823 dbus_address_entries_free (entries);
01824 return connection;
01825 }
01826
01835 void
01836 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01837 {
01838 _dbus_assert (connection != NULL);
01839 _dbus_assert (connection->generation == _dbus_current_generation);
01840
01841 CONNECTION_LOCK (connection);
01842 _dbus_connection_close_possibly_shared_and_unlock (connection);
01843 }
01844
01845 static DBusPreallocatedSend*
01846 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01847 {
01848 DBusPreallocatedSend *preallocated;
01849
01850 HAVE_LOCK_CHECK (connection);
01851
01852 _dbus_assert (connection != NULL);
01853
01854 preallocated = dbus_new (DBusPreallocatedSend, 1);
01855 if (preallocated == NULL)
01856 return NULL;
01857
01858 if (connection->link_cache != NULL)
01859 {
01860 preallocated->queue_link =
01861 _dbus_list_pop_first_link (&connection->link_cache);
01862 preallocated->queue_link->data = NULL;
01863 }
01864 else
01865 {
01866 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01867 if (preallocated->queue_link == NULL)
01868 goto failed_0;
01869 }
01870
01871 if (connection->link_cache != NULL)
01872 {
01873 preallocated->counter_link =
01874 _dbus_list_pop_first_link (&connection->link_cache);
01875 preallocated->counter_link->data = connection->outgoing_counter;
01876 }
01877 else
01878 {
01879 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01880 if (preallocated->counter_link == NULL)
01881 goto failed_1;
01882 }
01883
01884 _dbus_counter_ref (preallocated->counter_link->data);
01885
01886 preallocated->connection = connection;
01887
01888 return preallocated;
01889
01890 failed_1:
01891 _dbus_list_free_link (preallocated->queue_link);
01892 failed_0:
01893 dbus_free (preallocated);
01894
01895 return NULL;
01896 }
01897
01898
01899 static void
01900 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01901 DBusPreallocatedSend *preallocated,
01902 DBusMessage *message,
01903 dbus_uint32_t *client_serial)
01904 {
01905 dbus_uint32_t serial;
01906 const char *sig;
01907
01908 preallocated->queue_link->data = message;
01909 _dbus_list_prepend_link (&connection->outgoing_messages,
01910 preallocated->queue_link);
01911
01912 _dbus_message_add_size_counter_link (message,
01913 preallocated->counter_link);
01914
01915 dbus_free (preallocated);
01916 preallocated = NULL;
01917
01918 dbus_message_ref (message);
01919
01920 connection->n_outgoing += 1;
01921
01922 sig = dbus_message_get_signature (message);
01923
01924 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01925 message,
01926 dbus_message_get_type (message),
01927 dbus_message_get_path (message) ?
01928 dbus_message_get_path (message) :
01929 "no path",
01930 dbus_message_get_interface (message) ?
01931 dbus_message_get_interface (message) :
01932 "no interface",
01933 dbus_message_get_member (message) ?
01934 dbus_message_get_member (message) :
01935 "no member",
01936 sig,
01937 dbus_message_get_destination (message) ?
01938 dbus_message_get_destination (message) :
01939 "null",
01940 connection,
01941 connection->n_outgoing);
01942
01943 if (dbus_message_get_serial (message) == 0)
01944 {
01945 serial = _dbus_connection_get_next_client_serial (connection);
01946 _dbus_message_set_serial (message, serial);
01947 if (client_serial)
01948 *client_serial = serial;
01949 }
01950 else
01951 {
01952 if (client_serial)
01953 *client_serial = dbus_message_get_serial (message);
01954 }
01955
01956 _dbus_verbose ("Message %p serial is %u\n",
01957 message, dbus_message_get_serial (message));
01958
01959 _dbus_message_lock (message);
01960
01961
01962
01963
01964 _dbus_connection_do_iteration_unlocked (connection,
01965 DBUS_ITERATION_DO_WRITING,
01966 -1);
01967
01968
01969 if (connection->n_outgoing > 0)
01970 _dbus_connection_wakeup_mainloop (connection);
01971 }
01972
01973 static void
01974 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
01975 DBusPreallocatedSend *preallocated,
01976 DBusMessage *message,
01977 dbus_uint32_t *client_serial)
01978 {
01979 DBusDispatchStatus status;
01980
01981 HAVE_LOCK_CHECK (connection);
01982
01983 _dbus_connection_send_preallocated_unlocked_no_update (connection,
01984 preallocated,
01985 message, client_serial);
01986
01987 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01988 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01989
01990
01991 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01992 }
01993
02003 dbus_bool_t
02004 _dbus_connection_send_and_unlock (DBusConnection *connection,
02005 DBusMessage *message,
02006 dbus_uint32_t *client_serial)
02007 {
02008 DBusPreallocatedSend *preallocated;
02009
02010 _dbus_assert (connection != NULL);
02011 _dbus_assert (message != NULL);
02012
02013 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02014 if (preallocated == NULL)
02015 {
02016 CONNECTION_UNLOCK (connection);
02017 return FALSE;
02018 }
02019
02020 _dbus_connection_send_preallocated_and_unlock (connection,
02021 preallocated,
02022 message,
02023 client_serial);
02024 return TRUE;
02025 }
02026
02051 void
02052 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02053 {
02054 CONNECTION_LOCK (connection);
02055
02056 _dbus_assert (connection->refcount.value > 0);
02057
02058 if (connection->refcount.value == 1)
02059 _dbus_connection_close_possibly_shared_and_unlock (connection);
02060 else
02061 CONNECTION_UNLOCK (connection);
02062 }
02063
02064
02074 static void
02075 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02076 {
02077 if (timeout_milliseconds == -1)
02078 _dbus_sleep_milliseconds (1000);
02079 else if (timeout_milliseconds < 100)
02080 ;
02081 else if (timeout_milliseconds <= 1000)
02082 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02083 else
02084 _dbus_sleep_milliseconds (1000);
02085 }
02086
02087 static DBusMessage *
02088 generate_local_error_message (dbus_uint32_t serial,
02089 char *error_name,
02090 char *error_msg)
02091 {
02092 DBusMessage *message;
02093 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02094 if (!message)
02095 goto out;
02096
02097 if (!dbus_message_set_error_name (message, error_name))
02098 {
02099 dbus_message_unref (message);
02100 message = NULL;
02101 goto out;
02102 }
02103
02104 dbus_message_set_no_reply (message, TRUE);
02105
02106 if (!dbus_message_set_reply_serial (message,
02107 serial))
02108 {
02109 dbus_message_unref (message);
02110 message = NULL;
02111 goto out;
02112 }
02113
02114 if (error_msg != NULL)
02115 {
02116 DBusMessageIter iter;
02117
02118 dbus_message_iter_init_append (message, &iter);
02119 if (!dbus_message_iter_append_basic (&iter,
02120 DBUS_TYPE_STRING,
02121 &error_msg))
02122 {
02123 dbus_message_unref (message);
02124 message = NULL;
02125 goto out;
02126 }
02127 }
02128
02129 out:
02130 return message;
02131 }
02132
02133
02134
02135
02136
02137 static DBusMessage*
02138 check_for_reply_unlocked (DBusConnection *connection,
02139 dbus_uint32_t client_serial)
02140 {
02141 DBusList *link;
02142
02143 HAVE_LOCK_CHECK (connection);
02144
02145 link = _dbus_list_get_first_link (&connection->incoming_messages);
02146
02147 while (link != NULL)
02148 {
02149 DBusMessage *reply = link->data;
02150
02151 if (dbus_message_get_reply_serial (reply) == client_serial)
02152 {
02153 _dbus_list_remove_link (&connection->incoming_messages, link);
02154 connection->n_incoming -= 1;
02155 return reply;
02156 }
02157 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02158 }
02159
02160 return NULL;
02161 }
02162
02163 static void
02164 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02165 {
02166
02167
02168
02169
02170
02171 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02172 {
02173 DBusPendingCall *pending;
02174 DBusHashIter iter;
02175
02176 _dbus_hash_iter_init (connection->pending_replies, &iter);
02177 _dbus_hash_iter_next (&iter);
02178
02179 pending = _dbus_hash_iter_get_value (&iter);
02180 _dbus_pending_call_ref_unlocked (pending);
02181
02182 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02183 connection);
02184 _dbus_connection_remove_timeout_unlocked (connection,
02185 _dbus_pending_call_get_timeout_unlocked (pending));
02186 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02187 _dbus_hash_iter_remove_entry (&iter);
02188
02189 _dbus_pending_call_unref_and_unlock (pending);
02190 CONNECTION_LOCK (connection);
02191 }
02192 HAVE_LOCK_CHECK (connection);
02193 }
02194
02195 static void
02196 complete_pending_call_and_unlock (DBusConnection *connection,
02197 DBusPendingCall *pending,
02198 DBusMessage *message)
02199 {
02200 _dbus_pending_call_set_reply_unlocked (pending, message);
02201 _dbus_pending_call_ref_unlocked (pending);
02202 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02203
02204
02205 _dbus_pending_call_complete (pending);
02206 dbus_pending_call_unref (pending);
02207 }
02208
02209 static dbus_bool_t
02210 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02211 DBusPendingCall *pending)
02212 {
02213 DBusMessage *reply;
02214 DBusDispatchStatus status;
02215
02216 reply = check_for_reply_unlocked (connection,
02217 _dbus_pending_call_get_reply_serial_unlocked (pending));
02218 if (reply != NULL)
02219 {
02220 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02221
02222 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02223
02224 complete_pending_call_and_unlock (connection, pending, reply);
02225 dbus_message_unref (reply);
02226
02227 CONNECTION_LOCK (connection);
02228 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02229 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02230 dbus_pending_call_unref (pending);
02231
02232 return TRUE;
02233 }
02234
02235 return FALSE;
02236 }
02237
02252 void
02253 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02254 {
02255 long start_tv_sec, start_tv_usec;
02256 long end_tv_sec, end_tv_usec;
02257 long tv_sec, tv_usec;
02258 DBusDispatchStatus status;
02259 DBusConnection *connection;
02260 dbus_uint32_t client_serial;
02261 int timeout_milliseconds;
02262
02263 _dbus_assert (pending != NULL);
02264
02265 if (dbus_pending_call_get_completed (pending))
02266 return;
02267
02268 dbus_pending_call_ref (pending);
02269
02270 connection = _dbus_pending_call_get_connection_and_lock (pending);
02271
02272
02273 _dbus_connection_flush_unlocked (connection);
02274
02275 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02276
02277
02278
02279
02280
02281 timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02282
02283 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02284 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02285 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02286 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02287 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02288
02289 _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",
02290 timeout_milliseconds,
02291 client_serial,
02292 start_tv_sec, start_tv_usec,
02293 end_tv_sec, end_tv_usec);
02294
02295
02296
02297 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02298 return;
02299
02300
02301
02302 _dbus_connection_do_iteration_unlocked (connection,
02303 DBUS_ITERATION_DO_READING |
02304 DBUS_ITERATION_BLOCK,
02305 timeout_milliseconds);
02306
02307 recheck_status:
02308
02309 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02310
02311 HAVE_LOCK_CHECK (connection);
02312
02313
02314
02315 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02316
02317
02318
02319
02320 if (_dbus_pending_call_get_completed_unlocked (pending))
02321 {
02322 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02323 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02324 dbus_pending_call_unref (pending);
02325 return;
02326 }
02327
02328 if (status == DBUS_DISPATCH_DATA_REMAINS)
02329 {
02330 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02331 return;
02332 }
02333
02334 _dbus_get_current_time (&tv_sec, &tv_usec);
02335
02336 if (!_dbus_connection_get_is_connected_unlocked (connection))
02337 {
02338 DBusMessage *error_msg;
02339
02340 error_msg = generate_local_error_message (client_serial,
02341 DBUS_ERROR_DISCONNECTED,
02342 "Connection was disconnected before a reply was received");
02343
02344
02345 complete_pending_call_and_unlock (connection, pending, error_msg);
02346 dbus_pending_call_unref (pending);
02347 return;
02348 }
02349 else if (tv_sec < start_tv_sec)
02350 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02351 else if (connection->disconnect_message_link == NULL)
02352 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02353 else if (tv_sec < end_tv_sec ||
02354 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02355 {
02356 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02357 (end_tv_usec - tv_usec) / 1000;
02358 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02359 _dbus_assert (timeout_milliseconds >= 0);
02360
02361 if (status == DBUS_DISPATCH_NEED_MEMORY)
02362 {
02363
02364
02365
02366
02367 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02368
02369 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02370 }
02371 else
02372 {
02373
02374 _dbus_connection_do_iteration_unlocked (connection,
02375 DBUS_ITERATION_DO_READING |
02376 DBUS_ITERATION_BLOCK,
02377 timeout_milliseconds);
02378 }
02379
02380 goto recheck_status;
02381 }
02382
02383 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02384 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02385
02386 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02387
02388
02389 complete_pending_call_and_unlock (connection, pending, NULL);
02390
02391
02392 CONNECTION_LOCK (connection);
02393 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02394 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02395 dbus_pending_call_unref (pending);
02396 }
02397
02434 DBusConnection*
02435 dbus_connection_open (const char *address,
02436 DBusError *error)
02437 {
02438 DBusConnection *connection;
02439
02440 _dbus_return_val_if_fail (address != NULL, NULL);
02441 _dbus_return_val_if_error_is_set (error, NULL);
02442
02443 connection = _dbus_connection_open_internal (address,
02444 TRUE,
02445 error);
02446
02447 return connection;
02448 }
02449
02477 DBusConnection*
02478 dbus_connection_open_private (const char *address,
02479 DBusError *error)
02480 {
02481 DBusConnection *connection;
02482
02483 _dbus_return_val_if_fail (address != NULL, NULL);
02484 _dbus_return_val_if_error_is_set (error, NULL);
02485
02486 connection = _dbus_connection_open_internal (address,
02487 FALSE,
02488 error);
02489
02490 return connection;
02491 }
02492
02499 DBusConnection *
02500 dbus_connection_ref (DBusConnection *connection)
02501 {
02502 _dbus_return_val_if_fail (connection != NULL, NULL);
02503 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02504
02505
02506
02507
02508
02509 #ifdef DBUS_HAVE_ATOMIC_INT
02510 _dbus_atomic_inc (&connection->refcount);
02511 #else
02512 CONNECTION_LOCK (connection);
02513 _dbus_assert (connection->refcount.value > 0);
02514
02515 connection->refcount.value += 1;
02516 CONNECTION_UNLOCK (connection);
02517 #endif
02518
02519 return connection;
02520 }
02521
02522 static void
02523 free_outgoing_message (void *element,
02524 void *data)
02525 {
02526 DBusMessage *message = element;
02527 DBusConnection *connection = data;
02528
02529 _dbus_message_remove_size_counter (message,
02530 connection->outgoing_counter,
02531 NULL);
02532 dbus_message_unref (message);
02533 }
02534
02535
02536
02537
02538
02539 static void
02540 _dbus_connection_last_unref (DBusConnection *connection)
02541 {
02542 DBusList *link;
02543
02544 _dbus_verbose ("Finalizing connection %p\n", connection);
02545
02546 _dbus_assert (connection->refcount.value == 0);
02547
02548
02549
02550
02551 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02552 _dbus_assert (connection->server_guid == NULL);
02553
02554
02555 _dbus_object_tree_free_all_unlocked (connection->objects);
02556
02557 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02558 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02559 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02560
02561 _dbus_watch_list_free (connection->watches);
02562 connection->watches = NULL;
02563
02564 _dbus_timeout_list_free (connection->timeouts);
02565 connection->timeouts = NULL;
02566
02567 _dbus_data_slot_list_free (&connection->slot_list);
02568
02569 link = _dbus_list_get_first_link (&connection->filter_list);
02570 while (link != NULL)
02571 {
02572 DBusMessageFilter *filter = link->data;
02573 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02574
02575 filter->function = NULL;
02576 _dbus_message_filter_unref (filter);
02577 link->data = NULL;
02578
02579 link = next;
02580 }
02581 _dbus_list_clear (&connection->filter_list);
02582
02583
02584
02585 _dbus_object_tree_unref (connection->objects);
02586
02587 _dbus_hash_table_unref (connection->pending_replies);
02588 connection->pending_replies = NULL;
02589
02590 _dbus_list_clear (&connection->filter_list);
02591
02592 _dbus_list_foreach (&connection->outgoing_messages,
02593 free_outgoing_message,
02594 connection);
02595 _dbus_list_clear (&connection->outgoing_messages);
02596
02597 _dbus_list_foreach (&connection->incoming_messages,
02598 (DBusForeachFunction) dbus_message_unref,
02599 NULL);
02600 _dbus_list_clear (&connection->incoming_messages);
02601
02602 _dbus_counter_unref (connection->outgoing_counter);
02603
02604 _dbus_transport_unref (connection->transport);
02605
02606 if (connection->disconnect_message_link)
02607 {
02608 DBusMessage *message = connection->disconnect_message_link->data;
02609 dbus_message_unref (message);
02610 _dbus_list_free_link (connection->disconnect_message_link);
02611 }
02612
02613 _dbus_list_clear (&connection->link_cache);
02614
02615 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02616 _dbus_condvar_free_at_location (&connection->io_path_cond);
02617
02618 _dbus_mutex_free_at_location (&connection->io_path_mutex);
02619 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02620
02621 _dbus_mutex_free_at_location (&connection->mutex);
02622
02623 dbus_free (connection);
02624 }
02625
02645 void
02646 dbus_connection_unref (DBusConnection *connection)
02647 {
02648 dbus_bool_t last_unref;
02649
02650 _dbus_return_if_fail (connection != NULL);
02651 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02652
02653
02654
02655
02656
02657 #ifdef DBUS_HAVE_ATOMIC_INT
02658 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02659 #else
02660 CONNECTION_LOCK (connection);
02661
02662 _dbus_assert (connection->refcount.value > 0);
02663
02664 connection->refcount.value -= 1;
02665 last_unref = (connection->refcount.value == 0);
02666
02667 #if 0
02668 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02669 #endif
02670
02671 CONNECTION_UNLOCK (connection);
02672 #endif
02673
02674 if (last_unref)
02675 {
02676 #ifndef DBUS_DISABLE_CHECKS
02677 if (_dbus_transport_get_is_connected (connection->transport))
02678 {
02679 _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",
02680 connection->shareable ?
02681 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02682 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02683 return;
02684 }
02685 #endif
02686 _dbus_connection_last_unref (connection);
02687 }
02688 }
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699 static void
02700 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02701 {
02702 DBusDispatchStatus status;
02703
02704 HAVE_LOCK_CHECK (connection);
02705
02706 _dbus_verbose ("Disconnecting %p\n", connection);
02707
02708
02709
02710
02711
02712 _dbus_connection_ref_unlocked (connection);
02713
02714 _dbus_transport_disconnect (connection->transport);
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02726
02727
02728 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02729
02730
02731 dbus_connection_unref (connection);
02732 }
02733
02776 void
02777 dbus_connection_close (DBusConnection *connection)
02778 {
02779 _dbus_return_if_fail (connection != NULL);
02780 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02781
02782 CONNECTION_LOCK (connection);
02783
02784 #ifndef DBUS_DISABLE_CHECKS
02785 if (connection->shareable)
02786 {
02787 CONNECTION_UNLOCK (connection);
02788
02789 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02790 return;
02791 }
02792 #endif
02793
02794 _dbus_connection_close_possibly_shared_and_unlock (connection);
02795 }
02796
02797 static dbus_bool_t
02798 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02799 {
02800 HAVE_LOCK_CHECK (connection);
02801 return _dbus_transport_get_is_connected (connection->transport);
02802 }
02803
02817 dbus_bool_t
02818 dbus_connection_get_is_connected (DBusConnection *connection)
02819 {
02820 dbus_bool_t res;
02821
02822 _dbus_return_val_if_fail (connection != NULL, FALSE);
02823
02824 CONNECTION_LOCK (connection);
02825 res = _dbus_connection_get_is_connected_unlocked (connection);
02826 CONNECTION_UNLOCK (connection);
02827
02828 return res;
02829 }
02830
02839 dbus_bool_t
02840 dbus_connection_get_is_authenticated (DBusConnection *connection)
02841 {
02842 dbus_bool_t res;
02843
02844 _dbus_return_val_if_fail (connection != NULL, FALSE);
02845
02846 CONNECTION_LOCK (connection);
02847 res = _dbus_transport_get_is_authenticated (connection->transport);
02848 CONNECTION_UNLOCK (connection);
02849
02850 return res;
02851 }
02852
02873 dbus_bool_t
02874 dbus_connection_get_is_anonymous (DBusConnection *connection)
02875 {
02876 dbus_bool_t res;
02877
02878 _dbus_return_val_if_fail (connection != NULL, FALSE);
02879
02880 CONNECTION_LOCK (connection);
02881 res = _dbus_transport_get_is_anonymous (connection->transport);
02882 CONNECTION_UNLOCK (connection);
02883
02884 return res;
02885 }
02886
02918 char*
02919 dbus_connection_get_server_id (DBusConnection *connection)
02920 {
02921 char *id;
02922
02923 _dbus_return_val_if_fail (connection != NULL, FALSE);
02924
02925 CONNECTION_LOCK (connection);
02926 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02927 CONNECTION_UNLOCK (connection);
02928
02929 return id;
02930 }
02931
02945 void
02946 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02947 dbus_bool_t exit_on_disconnect)
02948 {
02949 _dbus_return_if_fail (connection != NULL);
02950
02951 CONNECTION_LOCK (connection);
02952 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02953 CONNECTION_UNLOCK (connection);
02954 }
02955
02965 DBusPreallocatedSend*
02966 dbus_connection_preallocate_send (DBusConnection *connection)
02967 {
02968 DBusPreallocatedSend *preallocated;
02969
02970 _dbus_return_val_if_fail (connection != NULL, NULL);
02971
02972 CONNECTION_LOCK (connection);
02973
02974 preallocated =
02975 _dbus_connection_preallocate_send_unlocked (connection);
02976
02977 CONNECTION_UNLOCK (connection);
02978
02979 return preallocated;
02980 }
02981
02991 void
02992 dbus_connection_free_preallocated_send (DBusConnection *connection,
02993 DBusPreallocatedSend *preallocated)
02994 {
02995 _dbus_return_if_fail (connection != NULL);
02996 _dbus_return_if_fail (preallocated != NULL);
02997 _dbus_return_if_fail (connection == preallocated->connection);
02998
02999 _dbus_list_free_link (preallocated->queue_link);
03000 _dbus_counter_unref (preallocated->counter_link->data);
03001 _dbus_list_free_link (preallocated->counter_link);
03002 dbus_free (preallocated);
03003 }
03004
03017 void
03018 dbus_connection_send_preallocated (DBusConnection *connection,
03019 DBusPreallocatedSend *preallocated,
03020 DBusMessage *message,
03021 dbus_uint32_t *client_serial)
03022 {
03023 _dbus_return_if_fail (connection != NULL);
03024 _dbus_return_if_fail (preallocated != NULL);
03025 _dbus_return_if_fail (message != NULL);
03026 _dbus_return_if_fail (preallocated->connection == connection);
03027 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03028 dbus_message_get_member (message) != NULL);
03029 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03030 (dbus_message_get_interface (message) != NULL &&
03031 dbus_message_get_member (message) != NULL));
03032
03033 CONNECTION_LOCK (connection);
03034 _dbus_connection_send_preallocated_and_unlock (connection,
03035 preallocated,
03036 message, client_serial);
03037 }
03038
03039 static dbus_bool_t
03040 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03041 DBusMessage *message,
03042 dbus_uint32_t *client_serial)
03043 {
03044 DBusPreallocatedSend *preallocated;
03045
03046 _dbus_assert (connection != NULL);
03047 _dbus_assert (message != NULL);
03048
03049 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03050 if (preallocated == NULL)
03051 return FALSE;
03052
03053 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03054 preallocated,
03055 message,
03056 client_serial);
03057 return TRUE;
03058 }
03059
03087 dbus_bool_t
03088 dbus_connection_send (DBusConnection *connection,
03089 DBusMessage *message,
03090 dbus_uint32_t *serial)
03091 {
03092 _dbus_return_val_if_fail (connection != NULL, FALSE);
03093 _dbus_return_val_if_fail (message != NULL, FALSE);
03094
03095 CONNECTION_LOCK (connection);
03096
03097 return _dbus_connection_send_and_unlock (connection,
03098 message,
03099 serial);
03100 }
03101
03102 static dbus_bool_t
03103 reply_handler_timeout (void *data)
03104 {
03105 DBusConnection *connection;
03106 DBusDispatchStatus status;
03107 DBusPendingCall *pending = data;
03108
03109 connection = _dbus_pending_call_get_connection_and_lock (pending);
03110
03111 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03112 connection);
03113 _dbus_connection_remove_timeout_unlocked (connection,
03114 _dbus_pending_call_get_timeout_unlocked (pending));
03115 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03116
03117 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03118 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03119
03120
03121 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03122
03123 return TRUE;
03124 }
03125
03163 dbus_bool_t
03164 dbus_connection_send_with_reply (DBusConnection *connection,
03165 DBusMessage *message,
03166 DBusPendingCall **pending_return,
03167 int timeout_milliseconds)
03168 {
03169 DBusPendingCall *pending;
03170 dbus_int32_t serial = -1;
03171 DBusDispatchStatus status;
03172
03173 _dbus_return_val_if_fail (connection != NULL, FALSE);
03174 _dbus_return_val_if_fail (message != NULL, FALSE);
03175 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03176
03177 if (pending_return)
03178 *pending_return = NULL;
03179
03180 CONNECTION_LOCK (connection);
03181
03182 if (!_dbus_connection_get_is_connected_unlocked (connection))
03183 {
03184 CONNECTION_UNLOCK (connection);
03185
03186 return TRUE;
03187 }
03188
03189 pending = _dbus_pending_call_new_unlocked (connection,
03190 timeout_milliseconds,
03191 reply_handler_timeout);
03192
03193 if (pending == NULL)
03194 {
03195 CONNECTION_UNLOCK (connection);
03196 return FALSE;
03197 }
03198
03199
03200 serial = dbus_message_get_serial (message);
03201 if (serial == 0)
03202 {
03203 serial = _dbus_connection_get_next_client_serial (connection);
03204 _dbus_message_set_serial (message, serial);
03205 }
03206
03207 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03208 goto error;
03209
03210
03211
03212
03213
03214 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03215 pending))
03216 goto error;
03217
03218 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03219 {
03220 _dbus_connection_detach_pending_call_and_unlock (connection,
03221 pending);
03222 goto error_unlocked;
03223 }
03224
03225 if (pending_return)
03226 *pending_return = pending;
03227 else
03228 {
03229 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03230
03231
03232
03233 }
03234
03235 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03236
03237
03238 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03239
03240 if (pending_return == NULL)
03241 dbus_pending_call_unref (pending);
03242
03243 return TRUE;
03244
03245 error:
03246 CONNECTION_UNLOCK (connection);
03247 error_unlocked:
03248 dbus_pending_call_unref (pending);
03249 return FALSE;
03250 }
03251
03282 DBusMessage*
03283 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03284 DBusMessage *message,
03285 int timeout_milliseconds,
03286 DBusError *error)
03287 {
03288 DBusMessage *reply;
03289 DBusPendingCall *pending;
03290
03291 _dbus_return_val_if_fail (connection != NULL, NULL);
03292 _dbus_return_val_if_fail (message != NULL, NULL);
03293 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03294 _dbus_return_val_if_error_is_set (error, NULL);
03295
03296 if (!dbus_connection_send_with_reply (connection, message,
03297 &pending, timeout_milliseconds))
03298 {
03299 _DBUS_SET_OOM (error);
03300 return NULL;
03301 }
03302
03303 if (pending == NULL)
03304 {
03305 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03306 return NULL;
03307 }
03308
03309 dbus_pending_call_block (pending);
03310
03311 reply = dbus_pending_call_steal_reply (pending);
03312 dbus_pending_call_unref (pending);
03313
03314
03315
03316
03317 _dbus_assert (reply != NULL);
03318
03319 if (dbus_set_error_from_message (error, reply))
03320 {
03321 dbus_message_unref (reply);
03322 return NULL;
03323 }
03324 else
03325 return reply;
03326 }
03327
03336 DBusDispatchStatus
03337 _dbus_connection_flush_unlocked (DBusConnection *connection)
03338 {
03339
03340
03341
03342
03343
03344 DBusDispatchStatus status;
03345
03346 HAVE_LOCK_CHECK (connection);
03347
03348 while (connection->n_outgoing > 0 &&
03349 _dbus_connection_get_is_connected_unlocked (connection))
03350 {
03351 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03352 HAVE_LOCK_CHECK (connection);
03353 _dbus_connection_do_iteration_unlocked (connection,
03354 DBUS_ITERATION_DO_READING |
03355 DBUS_ITERATION_DO_WRITING |
03356 DBUS_ITERATION_BLOCK,
03357 -1);
03358 }
03359
03360 HAVE_LOCK_CHECK (connection);
03361 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03362 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03363
03364 HAVE_LOCK_CHECK (connection);
03365 return status;
03366 }
03367
03373 void
03374 dbus_connection_flush (DBusConnection *connection)
03375 {
03376
03377
03378
03379
03380
03381 DBusDispatchStatus status;
03382
03383 _dbus_return_if_fail (connection != NULL);
03384
03385 CONNECTION_LOCK (connection);
03386
03387 status = _dbus_connection_flush_unlocked (connection);
03388
03389 HAVE_LOCK_CHECK (connection);
03390
03391 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03392
03393 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03394 }
03395
03406 static dbus_bool_t
03407 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03408 int timeout_milliseconds,
03409 dbus_bool_t dispatch)
03410 {
03411 DBusDispatchStatus dstatus;
03412 dbus_bool_t no_progress_possible;
03413
03414 dbus_connection_ref (connection);
03415
03416 dstatus = dbus_connection_get_dispatch_status (connection);
03417
03418 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03419 {
03420 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03421 dbus_connection_dispatch (connection);
03422 CONNECTION_LOCK (connection);
03423 }
03424 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03425 {
03426 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03427 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03428 CONNECTION_LOCK (connection);
03429 }
03430 else
03431 {
03432 CONNECTION_LOCK (connection);
03433 if (_dbus_connection_get_is_connected_unlocked (connection))
03434 {
03435 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03436 _dbus_connection_do_iteration_unlocked (connection,
03437 DBUS_ITERATION_DO_READING |
03438 DBUS_ITERATION_DO_WRITING |
03439 DBUS_ITERATION_BLOCK,
03440 timeout_milliseconds);
03441 }
03442 }
03443
03444 HAVE_LOCK_CHECK (connection);
03445
03446
03447
03448
03449 if (dispatch)
03450 no_progress_possible = connection->n_incoming == 0 &&
03451 connection->disconnect_message_link == NULL;
03452 else
03453 no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03454 CONNECTION_UNLOCK (connection);
03455 dbus_connection_unref (connection);
03456 return !no_progress_possible;
03457 }
03458
03459
03494 dbus_bool_t
03495 dbus_connection_read_write_dispatch (DBusConnection *connection,
03496 int timeout_milliseconds)
03497 {
03498 _dbus_return_val_if_fail (connection != NULL, FALSE);
03499 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03500 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03501 }
03502
03526 dbus_bool_t
03527 dbus_connection_read_write (DBusConnection *connection,
03528 int timeout_milliseconds)
03529 {
03530 _dbus_return_val_if_fail (connection != NULL, FALSE);
03531 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03532 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03533 }
03534
03535
03536
03537
03538
03539
03540 static void
03541 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03542 DBusMessage *head_of_queue)
03543 {
03544 HAVE_LOCK_CHECK (connection);
03545
03546
03547 if (connection->disconnect_message_link == NULL &&
03548 dbus_message_is_signal (head_of_queue,
03549 DBUS_INTERFACE_LOCAL,
03550 "Disconnected"))
03551 {
03552 connection->disconnected_message_arrived = TRUE;
03553 }
03554 }
03555
03575 DBusMessage*
03576 dbus_connection_borrow_message (DBusConnection *connection)
03577 {
03578 DBusDispatchStatus status;
03579 DBusMessage *message;
03580
03581 _dbus_return_val_if_fail (connection != NULL, NULL);
03582
03583 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03584
03585
03586
03587
03588 status = dbus_connection_get_dispatch_status (connection);
03589 if (status != DBUS_DISPATCH_DATA_REMAINS)
03590 return NULL;
03591
03592 CONNECTION_LOCK (connection);
03593
03594 _dbus_connection_acquire_dispatch (connection);
03595
03596
03597 _dbus_assert (connection->message_borrowed == NULL);
03598
03599 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03600
03601 message = connection->message_borrowed;
03602
03603 check_disconnected_message_arrived_unlocked (connection, message);
03604
03605
03606 if (message == NULL)
03607 _dbus_connection_release_dispatch (connection);
03608
03609 CONNECTION_UNLOCK (connection);
03610
03611
03612
03613 return message;
03614 }
03615
03624 void
03625 dbus_connection_return_message (DBusConnection *connection,
03626 DBusMessage *message)
03627 {
03628 DBusDispatchStatus status;
03629
03630 _dbus_return_if_fail (connection != NULL);
03631 _dbus_return_if_fail (message != NULL);
03632 _dbus_return_if_fail (message == connection->message_borrowed);
03633 _dbus_return_if_fail (connection->dispatch_acquired);
03634
03635 CONNECTION_LOCK (connection);
03636
03637 _dbus_assert (message == connection->message_borrowed);
03638
03639 connection->message_borrowed = NULL;
03640
03641 _dbus_connection_release_dispatch (connection);
03642
03643 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03644 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03645 }
03646
03656 void
03657 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03658 DBusMessage *message)
03659 {
03660 DBusMessage *pop_message;
03661 DBusDispatchStatus status;
03662
03663 _dbus_return_if_fail (connection != NULL);
03664 _dbus_return_if_fail (message != NULL);
03665 _dbus_return_if_fail (message == connection->message_borrowed);
03666 _dbus_return_if_fail (connection->dispatch_acquired);
03667
03668 CONNECTION_LOCK (connection);
03669
03670 _dbus_assert (message == connection->message_borrowed);
03671
03672 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03673 _dbus_assert (message == pop_message);
03674
03675 connection->n_incoming -= 1;
03676
03677 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03678 message, connection->n_incoming);
03679
03680 connection->message_borrowed = NULL;
03681
03682 _dbus_connection_release_dispatch (connection);
03683
03684 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03685 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03686 }
03687
03688
03689
03690
03691 static DBusList*
03692 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03693 {
03694 HAVE_LOCK_CHECK (connection);
03695
03696 _dbus_assert (connection->message_borrowed == NULL);
03697
03698 if (connection->n_incoming > 0)
03699 {
03700 DBusList *link;
03701
03702 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03703 connection->n_incoming -= 1;
03704
03705 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03706 link->data,
03707 dbus_message_get_type (link->data),
03708 dbus_message_get_path (link->data) ?
03709 dbus_message_get_path (link->data) :
03710 "no path",
03711 dbus_message_get_interface (link->data) ?
03712 dbus_message_get_interface (link->data) :
03713 "no interface",
03714 dbus_message_get_member (link->data) ?
03715 dbus_message_get_member (link->data) :
03716 "no member",
03717 dbus_message_get_signature (link->data),
03718 connection, connection->n_incoming);
03719
03720 check_disconnected_message_arrived_unlocked (connection, link->data);
03721
03722 return link;
03723 }
03724 else
03725 return NULL;
03726 }
03727
03728
03729
03730
03731 static DBusMessage*
03732 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03733 {
03734 DBusList *link;
03735
03736 HAVE_LOCK_CHECK (connection);
03737
03738 link = _dbus_connection_pop_message_link_unlocked (connection);
03739
03740 if (link != NULL)
03741 {
03742 DBusMessage *message;
03743
03744 message = link->data;
03745
03746 _dbus_list_free_link (link);
03747
03748 return message;
03749 }
03750 else
03751 return NULL;
03752 }
03753
03754 static void
03755 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03756 DBusList *message_link)
03757 {
03758 HAVE_LOCK_CHECK (connection);
03759
03760 _dbus_assert (message_link != NULL);
03761
03762 _dbus_assert (connection->message_borrowed == NULL);
03763
03764 _dbus_assert (connection->dispatch_acquired);
03765
03766 _dbus_list_prepend_link (&connection->incoming_messages,
03767 message_link);
03768 connection->n_incoming += 1;
03769
03770 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03771 message_link->data,
03772 dbus_message_get_type (message_link->data),
03773 dbus_message_get_interface (message_link->data) ?
03774 dbus_message_get_interface (message_link->data) :
03775 "no interface",
03776 dbus_message_get_member (message_link->data) ?
03777 dbus_message_get_member (message_link->data) :
03778 "no member",
03779 dbus_message_get_signature (message_link->data),
03780 connection, connection->n_incoming);
03781 }
03782
03802 DBusMessage*
03803 dbus_connection_pop_message (DBusConnection *connection)
03804 {
03805 DBusMessage *message;
03806 DBusDispatchStatus status;
03807
03808 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03809
03810
03811
03812
03813 status = dbus_connection_get_dispatch_status (connection);
03814 if (status != DBUS_DISPATCH_DATA_REMAINS)
03815 return NULL;
03816
03817 CONNECTION_LOCK (connection);
03818 _dbus_connection_acquire_dispatch (connection);
03819 HAVE_LOCK_CHECK (connection);
03820
03821 message = _dbus_connection_pop_message_unlocked (connection);
03822
03823 _dbus_verbose ("Returning popped message %p\n", message);
03824
03825 _dbus_connection_release_dispatch (connection);
03826
03827 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03828 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03829
03830 return message;
03831 }
03832
03840 static void
03841 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03842 {
03843 HAVE_LOCK_CHECK (connection);
03844
03845 _dbus_connection_ref_unlocked (connection);
03846 CONNECTION_UNLOCK (connection);
03847
03848 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03849 _dbus_mutex_lock (connection->dispatch_mutex);
03850
03851 while (connection->dispatch_acquired)
03852 {
03853 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03854 _dbus_condvar_wait (connection->dispatch_cond,
03855 connection->dispatch_mutex);
03856 }
03857
03858 _dbus_assert (!connection->dispatch_acquired);
03859
03860 connection->dispatch_acquired = TRUE;
03861
03862 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03863 _dbus_mutex_unlock (connection->dispatch_mutex);
03864
03865 CONNECTION_LOCK (connection);
03866 _dbus_connection_unref_unlocked (connection);
03867 }
03868
03876 static void
03877 _dbus_connection_release_dispatch (DBusConnection *connection)
03878 {
03879 HAVE_LOCK_CHECK (connection);
03880
03881 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03882 _dbus_mutex_lock (connection->dispatch_mutex);
03883
03884 _dbus_assert (connection->dispatch_acquired);
03885
03886 connection->dispatch_acquired = FALSE;
03887 _dbus_condvar_wake_one (connection->dispatch_cond);
03888
03889 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03890 _dbus_mutex_unlock (connection->dispatch_mutex);
03891 }
03892
03893 static void
03894 _dbus_connection_failed_pop (DBusConnection *connection,
03895 DBusList *message_link)
03896 {
03897 _dbus_list_prepend_link (&connection->incoming_messages,
03898 message_link);
03899 connection->n_incoming += 1;
03900 }
03901
03902
03903 static void
03904 notify_disconnected_unlocked (DBusConnection *connection)
03905 {
03906 HAVE_LOCK_CHECK (connection);
03907
03908
03909
03910
03911
03912
03913
03914 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03915
03916
03917
03918
03919
03920 if (connection->n_outgoing > 0)
03921 {
03922 DBusList *link;
03923
03924 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03925 connection->n_outgoing);
03926
03927 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03928 {
03929 _dbus_connection_message_sent (connection, link->data);
03930 }
03931 }
03932 }
03933
03934
03935 static DBusDispatchStatus
03936 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03937 {
03938 HAVE_LOCK_CHECK (connection);
03939
03940 if (connection->disconnect_message_link != NULL)
03941 {
03942 _dbus_verbose ("Sending disconnect message from %s\n",
03943 _DBUS_FUNCTION_NAME);
03944
03945
03946
03947
03948 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03949
03950
03951
03952
03953 _dbus_connection_queue_synthesized_message_link (connection,
03954 connection->disconnect_message_link);
03955 connection->disconnect_message_link = NULL;
03956
03957 return DBUS_DISPATCH_DATA_REMAINS;
03958 }
03959
03960 return DBUS_DISPATCH_COMPLETE;
03961 }
03962
03963 static DBusDispatchStatus
03964 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03965 {
03966 HAVE_LOCK_CHECK (connection);
03967
03968 if (connection->n_incoming > 0)
03969 return DBUS_DISPATCH_DATA_REMAINS;
03970 else if (!_dbus_transport_queue_messages (connection->transport))
03971 return DBUS_DISPATCH_NEED_MEMORY;
03972 else
03973 {
03974 DBusDispatchStatus status;
03975 dbus_bool_t is_connected;
03976
03977 status = _dbus_transport_get_dispatch_status (connection->transport);
03978 is_connected = _dbus_transport_get_is_connected (connection->transport);
03979
03980 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03981 DISPATCH_STATUS_NAME (status), is_connected);
03982
03983 if (!is_connected)
03984 {
03985
03986
03987
03988
03989
03990
03991 notify_disconnected_unlocked (connection);
03992
03993
03994
03995
03996
03997
03998 if (status == DBUS_DISPATCH_COMPLETE)
03999 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04000 }
04001
04002 if (status != DBUS_DISPATCH_COMPLETE)
04003 return status;
04004 else if (connection->n_incoming > 0)
04005 return DBUS_DISPATCH_DATA_REMAINS;
04006 else
04007 return DBUS_DISPATCH_COMPLETE;
04008 }
04009 }
04010
04011 static void
04012 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04013 DBusDispatchStatus new_status)
04014 {
04015 dbus_bool_t changed;
04016 DBusDispatchStatusFunction function;
04017 void *data;
04018
04019 HAVE_LOCK_CHECK (connection);
04020
04021 _dbus_connection_ref_unlocked (connection);
04022
04023 changed = new_status != connection->last_dispatch_status;
04024
04025 connection->last_dispatch_status = new_status;
04026
04027 function = connection->dispatch_status_function;
04028 data = connection->dispatch_status_data;
04029
04030 if (connection->disconnected_message_arrived &&
04031 !connection->disconnected_message_processed)
04032 {
04033 connection->disconnected_message_processed = TRUE;
04034
04035
04036
04037
04038
04039 connection_forget_shared_unlocked (connection);
04040
04041 if (connection->exit_on_disconnect)
04042 {
04043 CONNECTION_UNLOCK (connection);
04044
04045 _dbus_verbose ("Exiting on Disconnected signal\n");
04046 _dbus_exit (1);
04047 _dbus_assert_not_reached ("Call to exit() returned");
04048 }
04049 }
04050
04051
04052 CONNECTION_UNLOCK (connection);
04053
04054 if (changed && function)
04055 {
04056 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04057 connection, new_status,
04058 DISPATCH_STATUS_NAME (new_status));
04059 (* function) (connection, new_status, data);
04060 }
04061
04062 dbus_connection_unref (connection);
04063 }
04064
04090 DBusDispatchStatus
04091 dbus_connection_get_dispatch_status (DBusConnection *connection)
04092 {
04093 DBusDispatchStatus status;
04094
04095 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04096
04097 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04098
04099 CONNECTION_LOCK (connection);
04100
04101 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04102
04103 CONNECTION_UNLOCK (connection);
04104
04105 return status;
04106 }
04107
04111 static DBusHandlerResult
04112 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04113 DBusMessage *message)
04114 {
04115 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04116 {
04117
04118 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04119 }
04120 else if (dbus_message_is_method_call (message,
04121 DBUS_INTERFACE_PEER,
04122 "Ping"))
04123 {
04124 DBusMessage *ret;
04125 dbus_bool_t sent;
04126
04127 ret = dbus_message_new_method_return (message);
04128 if (ret == NULL)
04129 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04130
04131 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04132
04133 dbus_message_unref (ret);
04134
04135 if (!sent)
04136 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04137
04138 return DBUS_HANDLER_RESULT_HANDLED;
04139 }
04140 else if (dbus_message_is_method_call (message,
04141 DBUS_INTERFACE_PEER,
04142 "GetMachineId"))
04143 {
04144 DBusMessage *ret;
04145 dbus_bool_t sent;
04146 DBusString uuid;
04147
04148 ret = dbus_message_new_method_return (message);
04149 if (ret == NULL)
04150 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04151
04152 sent = FALSE;
04153 _dbus_string_init (&uuid);
04154 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04155 {
04156 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04157 if (dbus_message_append_args (ret,
04158 DBUS_TYPE_STRING, &v_STRING,
04159 DBUS_TYPE_INVALID))
04160 {
04161 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04162 }
04163 }
04164 _dbus_string_free (&uuid);
04165
04166 dbus_message_unref (ret);
04167
04168 if (!sent)
04169 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04170
04171 return DBUS_HANDLER_RESULT_HANDLED;
04172 }
04173 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04174 {
04175
04176
04177
04178
04179
04180 DBusMessage *ret;
04181 dbus_bool_t sent;
04182
04183 ret = dbus_message_new_error (message,
04184 DBUS_ERROR_UNKNOWN_METHOD,
04185 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04186 if (ret == NULL)
04187 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04188
04189 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04190
04191 dbus_message_unref (ret);
04192
04193 if (!sent)
04194 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04195
04196 return DBUS_HANDLER_RESULT_HANDLED;
04197 }
04198 else
04199 {
04200 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04201 }
04202 }
04203
04210 static DBusHandlerResult
04211 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04212 DBusMessage *message)
04213 {
04214
04215
04216
04217 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04218 }
04219
04262 DBusDispatchStatus
04263 dbus_connection_dispatch (DBusConnection *connection)
04264 {
04265 DBusMessage *message;
04266 DBusList *link, *filter_list_copy, *message_link;
04267 DBusHandlerResult result;
04268 DBusPendingCall *pending;
04269 dbus_int32_t reply_serial;
04270 DBusDispatchStatus status;
04271
04272 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04273
04274 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04275
04276 CONNECTION_LOCK (connection);
04277 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04278 if (status != DBUS_DISPATCH_DATA_REMAINS)
04279 {
04280
04281 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04282 return status;
04283 }
04284
04285
04286
04287
04288 _dbus_connection_ref_unlocked (connection);
04289
04290 _dbus_connection_acquire_dispatch (connection);
04291 HAVE_LOCK_CHECK (connection);
04292
04293 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04294 if (message_link == NULL)
04295 {
04296
04297
04298 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04299
04300 _dbus_connection_release_dispatch (connection);
04301
04302 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04303
04304 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04305
04306 dbus_connection_unref (connection);
04307
04308 return status;
04309 }
04310
04311 message = message_link->data;
04312
04313 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04314 message,
04315 dbus_message_get_type (message),
04316 dbus_message_get_interface (message) ?
04317 dbus_message_get_interface (message) :
04318 "no interface",
04319 dbus_message_get_member (message) ?
04320 dbus_message_get_member (message) :
04321 "no member",
04322 dbus_message_get_signature (message));
04323
04324 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04325
04326
04327
04328
04329
04330
04331
04332
04333 reply_serial = dbus_message_get_reply_serial (message);
04334 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04335 reply_serial);
04336 if (pending)
04337 {
04338 _dbus_verbose ("Dispatching a pending reply\n");
04339 complete_pending_call_and_unlock (connection, pending, message);
04340 pending = NULL;
04341
04342 CONNECTION_LOCK (connection);
04343 _dbus_verbose ("pending call completed in dispatch\n");
04344 result = DBUS_HANDLER_RESULT_HANDLED;
04345 goto out;
04346 }
04347
04348 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04349 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04350 goto out;
04351
04352 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04353 {
04354 _dbus_connection_release_dispatch (connection);
04355 HAVE_LOCK_CHECK (connection);
04356
04357 _dbus_connection_failed_pop (connection, message_link);
04358
04359
04360 _dbus_connection_update_dispatch_status_and_unlock (connection,
04361 DBUS_DISPATCH_NEED_MEMORY);
04362
04363 if (pending)
04364 dbus_pending_call_unref (pending);
04365 dbus_connection_unref (connection);
04366
04367 return DBUS_DISPATCH_NEED_MEMORY;
04368 }
04369
04370 _dbus_list_foreach (&filter_list_copy,
04371 (DBusForeachFunction)_dbus_message_filter_ref,
04372 NULL);
04373
04374
04375
04376
04377 CONNECTION_UNLOCK (connection);
04378
04379 link = _dbus_list_get_first_link (&filter_list_copy);
04380 while (link != NULL)
04381 {
04382 DBusMessageFilter *filter = link->data;
04383 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04384
04385 if (filter->function == NULL)
04386 {
04387 _dbus_verbose (" filter was removed in a callback function\n");
04388 link = next;
04389 continue;
04390 }
04391
04392 _dbus_verbose (" running filter on message %p\n", message);
04393 result = (* filter->function) (connection, message, filter->user_data);
04394
04395 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04396 break;
04397
04398 link = next;
04399 }
04400
04401 _dbus_list_foreach (&filter_list_copy,
04402 (DBusForeachFunction)_dbus_message_filter_unref,
04403 NULL);
04404 _dbus_list_clear (&filter_list_copy);
04405
04406 CONNECTION_LOCK (connection);
04407
04408 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04409 {
04410 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04411 goto out;
04412 }
04413 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04414 {
04415 _dbus_verbose ("filter handled message in dispatch\n");
04416 goto out;
04417 }
04418
04419
04420
04421
04422 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
04423 message,
04424 dbus_message_get_type (message),
04425 dbus_message_get_interface (message) ?
04426 dbus_message_get_interface (message) :
04427 "no interface",
04428 dbus_message_get_member (message) ?
04429 dbus_message_get_member (message) :
04430 "no member",
04431 dbus_message_get_signature (message));
04432
04433 HAVE_LOCK_CHECK (connection);
04434 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04435 message);
04436
04437 CONNECTION_LOCK (connection);
04438
04439 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04440 {
04441 _dbus_verbose ("object tree handled message in dispatch\n");
04442 goto out;
04443 }
04444
04445 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04446 {
04447 DBusMessage *reply;
04448 DBusString str;
04449 DBusPreallocatedSend *preallocated;
04450
04451 _dbus_verbose (" sending error %s\n",
04452 DBUS_ERROR_UNKNOWN_METHOD);
04453
04454 if (!_dbus_string_init (&str))
04455 {
04456 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04457 _dbus_verbose ("no memory for error string in dispatch\n");
04458 goto out;
04459 }
04460
04461 if (!_dbus_string_append_printf (&str,
04462 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04463 dbus_message_get_member (message),
04464 dbus_message_get_signature (message),
04465 dbus_message_get_interface (message)))
04466 {
04467 _dbus_string_free (&str);
04468 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04469 _dbus_verbose ("no memory for error string in dispatch\n");
04470 goto out;
04471 }
04472
04473 reply = dbus_message_new_error (message,
04474 DBUS_ERROR_UNKNOWN_METHOD,
04475 _dbus_string_get_const_data (&str));
04476 _dbus_string_free (&str);
04477
04478 if (reply == NULL)
04479 {
04480 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04481 _dbus_verbose ("no memory for error reply in dispatch\n");
04482 goto out;
04483 }
04484
04485 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04486
04487 if (preallocated == NULL)
04488 {
04489 dbus_message_unref (reply);
04490 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04491 _dbus_verbose ("no memory for error send in dispatch\n");
04492 goto out;
04493 }
04494
04495 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04496 reply, NULL);
04497
04498 dbus_message_unref (reply);
04499
04500 result = DBUS_HANDLER_RESULT_HANDLED;
04501 }
04502
04503 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04504 dbus_message_get_type (message),
04505 dbus_message_get_interface (message) ?
04506 dbus_message_get_interface (message) :
04507 "no interface",
04508 dbus_message_get_member (message) ?
04509 dbus_message_get_member (message) :
04510 "no member",
04511 dbus_message_get_signature (message),
04512 connection);
04513
04514 out:
04515 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04516 {
04517 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04518
04519
04520
04521
04522
04523 _dbus_connection_putback_message_link_unlocked (connection,
04524 message_link);
04525 }
04526 else
04527 {
04528 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04529
04530 _dbus_list_free_link (message_link);
04531 dbus_message_unref (message);
04532
04533
04534 }
04535
04536 _dbus_connection_release_dispatch (connection);
04537 HAVE_LOCK_CHECK (connection);
04538
04539 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04540 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04541
04542
04543 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04544
04545 dbus_connection_unref (connection);
04546
04547 return status;
04548 }
04549
04609 dbus_bool_t
04610 dbus_connection_set_watch_functions (DBusConnection *connection,
04611 DBusAddWatchFunction add_function,
04612 DBusRemoveWatchFunction remove_function,
04613 DBusWatchToggledFunction toggled_function,
04614 void *data,
04615 DBusFreeFunction free_data_function)
04616 {
04617 dbus_bool_t retval;
04618 DBusWatchList *watches;
04619
04620 _dbus_return_val_if_fail (connection != NULL, FALSE);
04621
04622 CONNECTION_LOCK (connection);
04623
04624 #ifndef DBUS_DISABLE_CHECKS
04625 if (connection->watches == NULL)
04626 {
04627 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04628 _DBUS_FUNCTION_NAME);
04629 return FALSE;
04630 }
04631 #endif
04632
04633
04634 _dbus_connection_ref_unlocked (connection);
04635
04636
04637
04638
04639
04640 watches = connection->watches;
04641 connection->watches = NULL;
04642 CONNECTION_UNLOCK (connection);
04643
04644 retval = _dbus_watch_list_set_functions (watches,
04645 add_function, remove_function,
04646 toggled_function,
04647 data, free_data_function);
04648 CONNECTION_LOCK (connection);
04649 connection->watches = watches;
04650
04651 CONNECTION_UNLOCK (connection);
04652
04653 dbus_connection_unref (connection);
04654
04655 return retval;
04656 }
04657
04691 dbus_bool_t
04692 dbus_connection_set_timeout_functions (DBusConnection *connection,
04693 DBusAddTimeoutFunction add_function,
04694 DBusRemoveTimeoutFunction remove_function,
04695 DBusTimeoutToggledFunction toggled_function,
04696 void *data,
04697 DBusFreeFunction free_data_function)
04698 {
04699 dbus_bool_t retval;
04700 DBusTimeoutList *timeouts;
04701
04702 _dbus_return_val_if_fail (connection != NULL, FALSE);
04703
04704 CONNECTION_LOCK (connection);
04705
04706 #ifndef DBUS_DISABLE_CHECKS
04707 if (connection->timeouts == NULL)
04708 {
04709 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04710 _DBUS_FUNCTION_NAME);
04711 return FALSE;
04712 }
04713 #endif
04714
04715
04716 _dbus_connection_ref_unlocked (connection);
04717
04718 timeouts = connection->timeouts;
04719 connection->timeouts = NULL;
04720 CONNECTION_UNLOCK (connection);
04721
04722 retval = _dbus_timeout_list_set_functions (timeouts,
04723 add_function, remove_function,
04724 toggled_function,
04725 data, free_data_function);
04726 CONNECTION_LOCK (connection);
04727 connection->timeouts = timeouts;
04728
04729 CONNECTION_UNLOCK (connection);
04730
04731 dbus_connection_unref (connection);
04732
04733 return retval;
04734 }
04735
04750 void
04751 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04752 DBusWakeupMainFunction wakeup_main_function,
04753 void *data,
04754 DBusFreeFunction free_data_function)
04755 {
04756 void *old_data;
04757 DBusFreeFunction old_free_data;
04758
04759 _dbus_return_if_fail (connection != NULL);
04760
04761 CONNECTION_LOCK (connection);
04762 old_data = connection->wakeup_main_data;
04763 old_free_data = connection->free_wakeup_main_data;
04764
04765 connection->wakeup_main_function = wakeup_main_function;
04766 connection->wakeup_main_data = data;
04767 connection->free_wakeup_main_data = free_data_function;
04768
04769 CONNECTION_UNLOCK (connection);
04770
04771
04772 if (old_free_data)
04773 (*old_free_data) (old_data);
04774 }
04775
04796 void
04797 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04798 DBusDispatchStatusFunction function,
04799 void *data,
04800 DBusFreeFunction free_data_function)
04801 {
04802 void *old_data;
04803 DBusFreeFunction old_free_data;
04804
04805 _dbus_return_if_fail (connection != NULL);
04806
04807 CONNECTION_LOCK (connection);
04808 old_data = connection->dispatch_status_data;
04809 old_free_data = connection->free_dispatch_status_data;
04810
04811 connection->dispatch_status_function = function;
04812 connection->dispatch_status_data = data;
04813 connection->free_dispatch_status_data = free_data_function;
04814
04815 CONNECTION_UNLOCK (connection);
04816
04817
04818 if (old_free_data)
04819 (*old_free_data) (old_data);
04820 }
04821
04841 dbus_bool_t
04842 dbus_connection_get_unix_fd (DBusConnection *connection,
04843 int *fd)
04844 {
04845 _dbus_return_val_if_fail (connection != NULL, FALSE);
04846 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04847
04848 #ifdef DBUS_WIN
04849
04850 return FALSE;
04851 #endif
04852
04853 return dbus_connection_get_socket(connection, fd);
04854 }
04855
04871 dbus_bool_t
04872 dbus_connection_get_socket(DBusConnection *connection,
04873 int *fd)
04874 {
04875 dbus_bool_t retval;
04876
04877 _dbus_return_val_if_fail (connection != NULL, FALSE);
04878 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04879
04880 CONNECTION_LOCK (connection);
04881
04882 retval = _dbus_transport_get_socket_fd (connection->transport,
04883 fd);
04884
04885 CONNECTION_UNLOCK (connection);
04886
04887 return retval;
04888 }
04889
04890
04913 dbus_bool_t
04914 dbus_connection_get_unix_user (DBusConnection *connection,
04915 unsigned long *uid)
04916 {
04917 dbus_bool_t result;
04918
04919 _dbus_return_val_if_fail (connection != NULL, FALSE);
04920 _dbus_return_val_if_fail (uid != NULL, FALSE);
04921
04922 CONNECTION_LOCK (connection);
04923
04924 if (!_dbus_transport_get_is_authenticated (connection->transport))
04925 result = FALSE;
04926 else
04927 result = _dbus_transport_get_unix_user (connection->transport,
04928 uid);
04929
04930 #ifdef DBUS_WIN
04931 _dbus_assert (!result);
04932 #endif
04933
04934 CONNECTION_UNLOCK (connection);
04935
04936 return result;
04937 }
04938
04949 dbus_bool_t
04950 dbus_connection_get_unix_process_id (DBusConnection *connection,
04951 unsigned long *pid)
04952 {
04953 dbus_bool_t result;
04954
04955 _dbus_return_val_if_fail (connection != NULL, FALSE);
04956 _dbus_return_val_if_fail (pid != NULL, FALSE);
04957
04958 CONNECTION_LOCK (connection);
04959
04960 if (!_dbus_transport_get_is_authenticated (connection->transport))
04961 result = FALSE;
04962 else
04963 result = _dbus_transport_get_unix_process_id (connection->transport,
04964 pid);
04965 #ifdef DBUS_WIN
04966 _dbus_assert (!result);
04967 #endif
04968
04969 CONNECTION_UNLOCK (connection);
04970
04971 return result;
04972 }
04973
04996 void
04997 dbus_connection_set_unix_user_function (DBusConnection *connection,
04998 DBusAllowUnixUserFunction function,
04999 void *data,
05000 DBusFreeFunction free_data_function)
05001 {
05002 void *old_data = NULL;
05003 DBusFreeFunction old_free_function = NULL;
05004
05005 _dbus_return_if_fail (connection != NULL);
05006
05007 CONNECTION_LOCK (connection);
05008 _dbus_transport_set_unix_user_function (connection->transport,
05009 function, data, free_data_function,
05010 &old_data, &old_free_function);
05011 CONNECTION_UNLOCK (connection);
05012
05013 if (old_free_function != NULL)
05014 (* old_free_function) (old_data);
05015 }
05016
05048 dbus_bool_t
05049 dbus_connection_get_windows_user (DBusConnection *connection,
05050 char **windows_sid_p)
05051 {
05052 dbus_bool_t result;
05053
05054 _dbus_return_val_if_fail (connection != NULL, FALSE);
05055 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05056
05057 CONNECTION_LOCK (connection);
05058
05059 if (!_dbus_transport_get_is_authenticated (connection->transport))
05060 result = FALSE;
05061 else
05062 result = _dbus_transport_get_windows_user (connection->transport,
05063 windows_sid_p);
05064
05065 #ifdef DBUS_UNIX
05066 _dbus_assert (!result);
05067 #endif
05068
05069 CONNECTION_UNLOCK (connection);
05070
05071 return result;
05072 }
05073
05095 void
05096 dbus_connection_set_windows_user_function (DBusConnection *connection,
05097 DBusAllowWindowsUserFunction function,
05098 void *data,
05099 DBusFreeFunction free_data_function)
05100 {
05101 void *old_data = NULL;
05102 DBusFreeFunction old_free_function = NULL;
05103
05104 _dbus_return_if_fail (connection != NULL);
05105
05106 CONNECTION_LOCK (connection);
05107 _dbus_transport_set_windows_user_function (connection->transport,
05108 function, data, free_data_function,
05109 &old_data, &old_free_function);
05110 CONNECTION_UNLOCK (connection);
05111
05112 if (old_free_function != NULL)
05113 (* old_free_function) (old_data);
05114 }
05115
05142 void
05143 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05144 dbus_bool_t value)
05145 {
05146 _dbus_return_if_fail (connection != NULL);
05147
05148 CONNECTION_LOCK (connection);
05149 _dbus_transport_set_allow_anonymous (connection->transport, value);
05150 CONNECTION_UNLOCK (connection);
05151 }
05152
05170 void
05171 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05172 dbus_bool_t value)
05173 {
05174 _dbus_return_if_fail (connection != NULL);
05175
05176 CONNECTION_LOCK (connection);
05177 connection->route_peer_messages = TRUE;
05178 CONNECTION_UNLOCK (connection);
05179 }
05180
05202 dbus_bool_t
05203 dbus_connection_add_filter (DBusConnection *connection,
05204 DBusHandleMessageFunction function,
05205 void *user_data,
05206 DBusFreeFunction free_data_function)
05207 {
05208 DBusMessageFilter *filter;
05209
05210 _dbus_return_val_if_fail (connection != NULL, FALSE);
05211 _dbus_return_val_if_fail (function != NULL, FALSE);
05212
05213 filter = dbus_new0 (DBusMessageFilter, 1);
05214 if (filter == NULL)
05215 return FALSE;
05216
05217 filter->refcount.value = 1;
05218
05219 CONNECTION_LOCK (connection);
05220
05221 if (!_dbus_list_append (&connection->filter_list,
05222 filter))
05223 {
05224 _dbus_message_filter_unref (filter);
05225 CONNECTION_UNLOCK (connection);
05226 return FALSE;
05227 }
05228
05229
05230
05231
05232
05233
05234 filter->function = function;
05235 filter->user_data = user_data;
05236 filter->free_user_data_function = free_data_function;
05237
05238 CONNECTION_UNLOCK (connection);
05239 return TRUE;
05240 }
05241
05254 void
05255 dbus_connection_remove_filter (DBusConnection *connection,
05256 DBusHandleMessageFunction function,
05257 void *user_data)
05258 {
05259 DBusList *link;
05260 DBusMessageFilter *filter;
05261
05262 _dbus_return_if_fail (connection != NULL);
05263 _dbus_return_if_fail (function != NULL);
05264
05265 CONNECTION_LOCK (connection);
05266
05267 filter = NULL;
05268
05269 link = _dbus_list_get_last_link (&connection->filter_list);
05270 while (link != NULL)
05271 {
05272 filter = link->data;
05273
05274 if (filter->function == function &&
05275 filter->user_data == user_data)
05276 {
05277 _dbus_list_remove_link (&connection->filter_list, link);
05278 filter->function = NULL;
05279
05280 break;
05281 }
05282
05283 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05284 }
05285
05286 CONNECTION_UNLOCK (connection);
05287
05288 #ifndef DBUS_DISABLE_CHECKS
05289 if (filter == NULL)
05290 {
05291 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05292 function, user_data);
05293 return;
05294 }
05295 #endif
05296
05297
05298 if (filter->free_user_data_function)
05299 (* filter->free_user_data_function) (filter->user_data);
05300
05301 filter->free_user_data_function = NULL;
05302 filter->user_data = NULL;
05303
05304 _dbus_message_filter_unref (filter);
05305 }
05306
05319 dbus_bool_t
05320 dbus_connection_try_register_object_path (DBusConnection *connection,
05321 const char *path,
05322 const DBusObjectPathVTable *vtable,
05323 void *user_data,
05324 DBusError *error)
05325 {
05326 char **decomposed_path;
05327 dbus_bool_t retval;
05328
05329 _dbus_return_val_if_fail (connection != NULL, FALSE);
05330 _dbus_return_val_if_fail (path != NULL, FALSE);
05331 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05332 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05333
05334 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05335 return FALSE;
05336
05337 CONNECTION_LOCK (connection);
05338
05339 retval = _dbus_object_tree_register (connection->objects,
05340 FALSE,
05341 (const char **) decomposed_path, vtable,
05342 user_data, error);
05343
05344 CONNECTION_UNLOCK (connection);
05345
05346 dbus_free_string_array (decomposed_path);
05347
05348 return retval;
05349 }
05350
05365 dbus_bool_t
05366 dbus_connection_register_object_path (DBusConnection *connection,
05367 const char *path,
05368 const DBusObjectPathVTable *vtable,
05369 void *user_data)
05370 {
05371 char **decomposed_path;
05372 dbus_bool_t retval;
05373 DBusError error = DBUS_ERROR_INIT;
05374
05375 _dbus_return_val_if_fail (connection != NULL, FALSE);
05376 _dbus_return_val_if_fail (path != NULL, FALSE);
05377 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05378 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05379
05380 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05381 return FALSE;
05382
05383 CONNECTION_LOCK (connection);
05384
05385 retval = _dbus_object_tree_register (connection->objects,
05386 FALSE,
05387 (const char **) decomposed_path, vtable,
05388 user_data, &error);
05389
05390 CONNECTION_UNLOCK (connection);
05391
05392 dbus_free_string_array (decomposed_path);
05393
05394 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05395 {
05396 _dbus_warn ("%s\n", error.message);
05397 dbus_error_free (&error);
05398 return FALSE;
05399 }
05400
05401 return retval;
05402 }
05403
05418 dbus_bool_t
05419 dbus_connection_try_register_fallback (DBusConnection *connection,
05420 const char *path,
05421 const DBusObjectPathVTable *vtable,
05422 void *user_data,
05423 DBusError *error)
05424 {
05425 char **decomposed_path;
05426 dbus_bool_t retval;
05427
05428 _dbus_return_val_if_fail (connection != NULL, FALSE);
05429 _dbus_return_val_if_fail (path != NULL, FALSE);
05430 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05431 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05432
05433 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05434 return FALSE;
05435
05436 CONNECTION_LOCK (connection);
05437
05438 retval = _dbus_object_tree_register (connection->objects,
05439 TRUE,
05440 (const char **) decomposed_path, vtable,
05441 user_data, error);
05442
05443 CONNECTION_UNLOCK (connection);
05444
05445 dbus_free_string_array (decomposed_path);
05446
05447 return retval;
05448 }
05449
05466 dbus_bool_t
05467 dbus_connection_register_fallback (DBusConnection *connection,
05468 const char *path,
05469 const DBusObjectPathVTable *vtable,
05470 void *user_data)
05471 {
05472 char **decomposed_path;
05473 dbus_bool_t retval;
05474 DBusError error = DBUS_ERROR_INIT;
05475
05476 _dbus_return_val_if_fail (connection != NULL, FALSE);
05477 _dbus_return_val_if_fail (path != NULL, FALSE);
05478 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05479 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05480
05481 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05482 return FALSE;
05483
05484 CONNECTION_LOCK (connection);
05485
05486 retval = _dbus_object_tree_register (connection->objects,
05487 TRUE,
05488 (const char **) decomposed_path, vtable,
05489 user_data, &error);
05490
05491 CONNECTION_UNLOCK (connection);
05492
05493 dbus_free_string_array (decomposed_path);
05494
05495 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05496 {
05497 _dbus_warn ("%s\n", error.message);
05498 dbus_error_free (&error);
05499 return FALSE;
05500 }
05501
05502 return retval;
05503 }
05504
05514 dbus_bool_t
05515 dbus_connection_unregister_object_path (DBusConnection *connection,
05516 const char *path)
05517 {
05518 char **decomposed_path;
05519
05520 _dbus_return_val_if_fail (connection != NULL, FALSE);
05521 _dbus_return_val_if_fail (path != NULL, FALSE);
05522 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05523
05524 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05525 return FALSE;
05526
05527 CONNECTION_LOCK (connection);
05528
05529 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05530
05531 dbus_free_string_array (decomposed_path);
05532
05533 return TRUE;
05534 }
05535
05546 dbus_bool_t
05547 dbus_connection_get_object_path_data (DBusConnection *connection,
05548 const char *path,
05549 void **data_p)
05550 {
05551 char **decomposed_path;
05552
05553 _dbus_return_val_if_fail (connection != NULL, FALSE);
05554 _dbus_return_val_if_fail (path != NULL, FALSE);
05555 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05556
05557 *data_p = NULL;
05558
05559 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05560 return FALSE;
05561
05562 CONNECTION_LOCK (connection);
05563
05564 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05565
05566 CONNECTION_UNLOCK (connection);
05567
05568 dbus_free_string_array (decomposed_path);
05569
05570 return TRUE;
05571 }
05572
05583 dbus_bool_t
05584 dbus_connection_list_registered (DBusConnection *connection,
05585 const char *parent_path,
05586 char ***child_entries)
05587 {
05588 char **decomposed_path;
05589 dbus_bool_t retval;
05590 _dbus_return_val_if_fail (connection != NULL, FALSE);
05591 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05592 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05593 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05594
05595 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05596 return FALSE;
05597
05598 CONNECTION_LOCK (connection);
05599
05600 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05601 (const char **) decomposed_path,
05602 child_entries);
05603 dbus_free_string_array (decomposed_path);
05604
05605 return retval;
05606 }
05607
05608 static DBusDataSlotAllocator slot_allocator;
05609 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05610
05625 dbus_bool_t
05626 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05627 {
05628 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05629 &_DBUS_LOCK_NAME (connection_slots),
05630 slot_p);
05631 }
05632
05644 void
05645 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05646 {
05647 _dbus_return_if_fail (*slot_p >= 0);
05648
05649 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05650 }
05651
05665 dbus_bool_t
05666 dbus_connection_set_data (DBusConnection *connection,
05667 dbus_int32_t slot,
05668 void *data,
05669 DBusFreeFunction free_data_func)
05670 {
05671 DBusFreeFunction old_free_func;
05672 void *old_data;
05673 dbus_bool_t retval;
05674
05675 _dbus_return_val_if_fail (connection != NULL, FALSE);
05676 _dbus_return_val_if_fail (slot >= 0, FALSE);
05677
05678 CONNECTION_LOCK (connection);
05679
05680 retval = _dbus_data_slot_list_set (&slot_allocator,
05681 &connection->slot_list,
05682 slot, data, free_data_func,
05683 &old_free_func, &old_data);
05684
05685 CONNECTION_UNLOCK (connection);
05686
05687 if (retval)
05688 {
05689
05690 if (old_free_func)
05691 (* old_free_func) (old_data);
05692 }
05693
05694 return retval;
05695 }
05696
05705 void*
05706 dbus_connection_get_data (DBusConnection *connection,
05707 dbus_int32_t slot)
05708 {
05709 void *res;
05710
05711 _dbus_return_val_if_fail (connection != NULL, NULL);
05712
05713 CONNECTION_LOCK (connection);
05714
05715 res = _dbus_data_slot_list_get (&slot_allocator,
05716 &connection->slot_list,
05717 slot);
05718
05719 CONNECTION_UNLOCK (connection);
05720
05721 return res;
05722 }
05723
05730 void
05731 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05732 {
05733 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05734 }
05735
05744 void
05745 dbus_connection_set_max_message_size (DBusConnection *connection,
05746 long size)
05747 {
05748 _dbus_return_if_fail (connection != NULL);
05749
05750 CONNECTION_LOCK (connection);
05751 _dbus_transport_set_max_message_size (connection->transport,
05752 size);
05753 CONNECTION_UNLOCK (connection);
05754 }
05755
05762 long
05763 dbus_connection_get_max_message_size (DBusConnection *connection)
05764 {
05765 long res;
05766
05767 _dbus_return_val_if_fail (connection != NULL, 0);
05768
05769 CONNECTION_LOCK (connection);
05770 res = _dbus_transport_get_max_message_size (connection->transport);
05771 CONNECTION_UNLOCK (connection);
05772 return res;
05773 }
05774
05800 void
05801 dbus_connection_set_max_received_size (DBusConnection *connection,
05802 long size)
05803 {
05804 _dbus_return_if_fail (connection != NULL);
05805
05806 CONNECTION_LOCK (connection);
05807 _dbus_transport_set_max_received_size (connection->transport,
05808 size);
05809 CONNECTION_UNLOCK (connection);
05810 }
05811
05818 long
05819 dbus_connection_get_max_received_size (DBusConnection *connection)
05820 {
05821 long res;
05822
05823 _dbus_return_val_if_fail (connection != NULL, 0);
05824
05825 CONNECTION_LOCK (connection);
05826 res = _dbus_transport_get_max_received_size (connection->transport);
05827 CONNECTION_UNLOCK (connection);
05828 return res;
05829 }
05830
05841 long
05842 dbus_connection_get_outgoing_size (DBusConnection *connection)
05843 {
05844 long res;
05845
05846 _dbus_return_val_if_fail (connection != NULL, 0);
05847
05848 CONNECTION_LOCK (connection);
05849 res = _dbus_counter_get_value (connection->outgoing_counter);
05850 CONNECTION_UNLOCK (connection);
05851 return res;
05852 }
05853