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