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
02826 void
02827 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02828 dbus_bool_t exit_on_disconnect)
02829 {
02830 _dbus_return_if_fail (connection != NULL);
02831
02832 CONNECTION_LOCK (connection);
02833 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02834 CONNECTION_UNLOCK (connection);
02835 }
02836
02846 DBusPreallocatedSend*
02847 dbus_connection_preallocate_send (DBusConnection *connection)
02848 {
02849 DBusPreallocatedSend *preallocated;
02850
02851 _dbus_return_val_if_fail (connection != NULL, NULL);
02852
02853 CONNECTION_LOCK (connection);
02854
02855 preallocated =
02856 _dbus_connection_preallocate_send_unlocked (connection);
02857
02858 CONNECTION_UNLOCK (connection);
02859
02860 return preallocated;
02861 }
02862
02872 void
02873 dbus_connection_free_preallocated_send (DBusConnection *connection,
02874 DBusPreallocatedSend *preallocated)
02875 {
02876 _dbus_return_if_fail (connection != NULL);
02877 _dbus_return_if_fail (preallocated != NULL);
02878 _dbus_return_if_fail (connection == preallocated->connection);
02879
02880 _dbus_list_free_link (preallocated->queue_link);
02881 _dbus_counter_unref (preallocated->counter_link->data);
02882 _dbus_list_free_link (preallocated->counter_link);
02883 dbus_free (preallocated);
02884 }
02885
02898 void
02899 dbus_connection_send_preallocated (DBusConnection *connection,
02900 DBusPreallocatedSend *preallocated,
02901 DBusMessage *message,
02902 dbus_uint32_t *client_serial)
02903 {
02904 _dbus_return_if_fail (connection != NULL);
02905 _dbus_return_if_fail (preallocated != NULL);
02906 _dbus_return_if_fail (message != NULL);
02907 _dbus_return_if_fail (preallocated->connection == connection);
02908 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02909 dbus_message_get_member (message) != NULL);
02910 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02911 (dbus_message_get_interface (message) != NULL &&
02912 dbus_message_get_member (message) != NULL));
02913
02914 CONNECTION_LOCK (connection);
02915 _dbus_connection_send_preallocated_and_unlock (connection,
02916 preallocated,
02917 message, client_serial);
02918 }
02919
02920 static dbus_bool_t
02921 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02922 DBusMessage *message,
02923 dbus_uint32_t *client_serial)
02924 {
02925 DBusPreallocatedSend *preallocated;
02926
02927 _dbus_assert (connection != NULL);
02928 _dbus_assert (message != NULL);
02929
02930 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02931 if (preallocated == NULL)
02932 return FALSE;
02933
02934 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02935 preallocated,
02936 message,
02937 client_serial);
02938 return TRUE;
02939 }
02940
02962 dbus_bool_t
02963 dbus_connection_send (DBusConnection *connection,
02964 DBusMessage *message,
02965 dbus_uint32_t *serial)
02966 {
02967 _dbus_return_val_if_fail (connection != NULL, FALSE);
02968 _dbus_return_val_if_fail (message != NULL, FALSE);
02969
02970 CONNECTION_LOCK (connection);
02971
02972 return _dbus_connection_send_and_unlock (connection,
02973 message,
02974 serial);
02975 }
02976
02977 static dbus_bool_t
02978 reply_handler_timeout (void *data)
02979 {
02980 DBusConnection *connection;
02981 DBusDispatchStatus status;
02982 DBusPendingCall *pending = data;
02983
02984 connection = _dbus_pending_call_get_connection_and_lock (pending);
02985
02986 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02987 connection);
02988 _dbus_connection_remove_timeout_unlocked (connection,
02989 _dbus_pending_call_get_timeout_unlocked (pending));
02990 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02991
02992 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02993 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02994
02995
02996 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02997
02998 return TRUE;
02999 }
03000
03038 dbus_bool_t
03039 dbus_connection_send_with_reply (DBusConnection *connection,
03040 DBusMessage *message,
03041 DBusPendingCall **pending_return,
03042 int timeout_milliseconds)
03043 {
03044 DBusPendingCall *pending;
03045 dbus_int32_t serial = -1;
03046 DBusDispatchStatus status;
03047
03048 _dbus_return_val_if_fail (connection != NULL, FALSE);
03049 _dbus_return_val_if_fail (message != NULL, FALSE);
03050 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03051
03052 if (pending_return)
03053 *pending_return = NULL;
03054
03055 CONNECTION_LOCK (connection);
03056
03057 if (!_dbus_connection_get_is_connected_unlocked (connection))
03058 {
03059 CONNECTION_UNLOCK (connection);
03060
03061 *pending_return = NULL;
03062
03063 return TRUE;
03064 }
03065
03066 pending = _dbus_pending_call_new_unlocked (connection,
03067 timeout_milliseconds,
03068 reply_handler_timeout);
03069
03070 if (pending == NULL)
03071 {
03072 CONNECTION_UNLOCK (connection);
03073 return FALSE;
03074 }
03075
03076
03077 serial = dbus_message_get_serial (message);
03078 if (serial == 0)
03079 {
03080 serial = _dbus_connection_get_next_client_serial (connection);
03081 _dbus_message_set_serial (message, serial);
03082 }
03083
03084 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03085 goto error;
03086
03087
03088
03089
03090
03091 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03092 pending))
03093 goto error;
03094
03095 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03096 {
03097 _dbus_connection_detach_pending_call_and_unlock (connection,
03098 pending);
03099 goto error_unlocked;
03100 }
03101
03102 if (pending_return)
03103 *pending_return = pending;
03104 else
03105 {
03106 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03107
03108
03109
03110 }
03111
03112 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03113
03114
03115 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03116
03117 if (pending_return == NULL)
03118 dbus_pending_call_unref (pending);
03119
03120 return TRUE;
03121
03122 error:
03123 CONNECTION_UNLOCK (connection);
03124 error_unlocked:
03125 dbus_pending_call_unref (pending);
03126 return FALSE;
03127 }
03128
03159 DBusMessage*
03160 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03161 DBusMessage *message,
03162 int timeout_milliseconds,
03163 DBusError *error)
03164 {
03165 DBusMessage *reply;
03166 DBusPendingCall *pending;
03167
03168 _dbus_return_val_if_fail (connection != NULL, NULL);
03169 _dbus_return_val_if_fail (message != NULL, NULL);
03170 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03171 _dbus_return_val_if_error_is_set (error, NULL);
03172
03173 if (!dbus_connection_send_with_reply (connection, message,
03174 &pending, timeout_milliseconds))
03175 {
03176 _DBUS_SET_OOM (error);
03177 return NULL;
03178 }
03179
03180 if (pending == NULL)
03181 {
03182 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03183 return NULL;
03184 }
03185
03186 dbus_pending_call_block (pending);
03187
03188 reply = dbus_pending_call_steal_reply (pending);
03189 dbus_pending_call_unref (pending);
03190
03191
03192
03193
03194 _dbus_assert (reply != NULL);
03195
03196 if (dbus_set_error_from_message (error, reply))
03197 {
03198 dbus_message_unref (reply);
03199 return NULL;
03200 }
03201 else
03202 return reply;
03203 }
03204
03213 DBusDispatchStatus
03214 _dbus_connection_flush_unlocked (DBusConnection *connection)
03215 {
03216
03217
03218
03219
03220
03221 DBusDispatchStatus status;
03222
03223 HAVE_LOCK_CHECK (connection);
03224
03225 while (connection->n_outgoing > 0 &&
03226 _dbus_connection_get_is_connected_unlocked (connection))
03227 {
03228 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03229 HAVE_LOCK_CHECK (connection);
03230 _dbus_connection_do_iteration_unlocked (connection,
03231 DBUS_ITERATION_DO_READING |
03232 DBUS_ITERATION_DO_WRITING |
03233 DBUS_ITERATION_BLOCK,
03234 -1);
03235 }
03236
03237 HAVE_LOCK_CHECK (connection);
03238 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03239 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03240
03241 HAVE_LOCK_CHECK (connection);
03242 return status;
03243 }
03244
03250 void
03251 dbus_connection_flush (DBusConnection *connection)
03252 {
03253
03254
03255
03256
03257
03258 DBusDispatchStatus status;
03259
03260 _dbus_return_if_fail (connection != NULL);
03261
03262 CONNECTION_LOCK (connection);
03263
03264 status = _dbus_connection_flush_unlocked (connection);
03265
03266 HAVE_LOCK_CHECK (connection);
03267
03268 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03269
03270 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03271 }
03272
03283 static dbus_bool_t
03284 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03285 int timeout_milliseconds,
03286 dbus_bool_t dispatch)
03287 {
03288 DBusDispatchStatus dstatus;
03289 dbus_bool_t no_progress_possible;
03290
03291 dstatus = dbus_connection_get_dispatch_status (connection);
03292
03293 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03294 {
03295 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03296 dbus_connection_dispatch (connection);
03297 CONNECTION_LOCK (connection);
03298 }
03299 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03300 {
03301 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03302 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03303 CONNECTION_LOCK (connection);
03304 }
03305 else
03306 {
03307 CONNECTION_LOCK (connection);
03308 if (_dbus_connection_get_is_connected_unlocked (connection))
03309 {
03310 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03311 _dbus_connection_do_iteration_unlocked (connection,
03312 DBUS_ITERATION_DO_READING |
03313 DBUS_ITERATION_DO_WRITING |
03314 DBUS_ITERATION_BLOCK,
03315 timeout_milliseconds);
03316 }
03317 }
03318
03319 HAVE_LOCK_CHECK (connection);
03320
03321
03322
03323
03324 if (dispatch)
03325 no_progress_possible = connection->n_incoming == 0 &&
03326 connection->disconnect_message_link == NULL;
03327 else
03328 no_progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03329 CONNECTION_UNLOCK (connection);
03330 return !no_progress_possible;
03331 }
03332
03333
03368 dbus_bool_t
03369 dbus_connection_read_write_dispatch (DBusConnection *connection,
03370 int timeout_milliseconds)
03371 {
03372 _dbus_return_val_if_fail (connection != NULL, FALSE);
03373 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03374 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03375 }
03376
03400 dbus_bool_t
03401 dbus_connection_read_write (DBusConnection *connection,
03402 int timeout_milliseconds)
03403 {
03404 _dbus_return_val_if_fail (connection != NULL, FALSE);
03405 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03406 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03407 }
03408
03409
03410
03411
03412
03413
03414 static void
03415 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03416 DBusMessage *head_of_queue)
03417 {
03418 HAVE_LOCK_CHECK (connection);
03419
03420
03421 if (connection->disconnect_message_link == NULL &&
03422 dbus_message_is_signal (head_of_queue,
03423 DBUS_INTERFACE_LOCAL,
03424 "Disconnected"))
03425 {
03426 connection->disconnected_message_arrived = TRUE;
03427 }
03428 }
03429
03449 DBusMessage*
03450 dbus_connection_borrow_message (DBusConnection *connection)
03451 {
03452 DBusDispatchStatus status;
03453 DBusMessage *message;
03454
03455 _dbus_return_val_if_fail (connection != NULL, NULL);
03456
03457 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03458
03459
03460
03461
03462 status = dbus_connection_get_dispatch_status (connection);
03463 if (status != DBUS_DISPATCH_DATA_REMAINS)
03464 return NULL;
03465
03466 CONNECTION_LOCK (connection);
03467
03468 _dbus_connection_acquire_dispatch (connection);
03469
03470
03471 _dbus_assert (connection->message_borrowed == NULL);
03472
03473 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03474
03475 message = connection->message_borrowed;
03476
03477 check_disconnected_message_arrived_unlocked (connection, message);
03478
03479
03480 if (message == NULL)
03481 _dbus_connection_release_dispatch (connection);
03482
03483 CONNECTION_UNLOCK (connection);
03484
03485
03486
03487 return message;
03488 }
03489
03498 void
03499 dbus_connection_return_message (DBusConnection *connection,
03500 DBusMessage *message)
03501 {
03502 DBusDispatchStatus status;
03503
03504 _dbus_return_if_fail (connection != NULL);
03505 _dbus_return_if_fail (message != NULL);
03506 _dbus_return_if_fail (message == connection->message_borrowed);
03507 _dbus_return_if_fail (connection->dispatch_acquired);
03508
03509 CONNECTION_LOCK (connection);
03510
03511 _dbus_assert (message == connection->message_borrowed);
03512
03513 connection->message_borrowed = NULL;
03514
03515 _dbus_connection_release_dispatch (connection);
03516
03517 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03518 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03519 }
03520
03530 void
03531 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03532 DBusMessage *message)
03533 {
03534 DBusMessage *pop_message;
03535 DBusDispatchStatus status;
03536
03537 _dbus_return_if_fail (connection != NULL);
03538 _dbus_return_if_fail (message != NULL);
03539 _dbus_return_if_fail (message == connection->message_borrowed);
03540 _dbus_return_if_fail (connection->dispatch_acquired);
03541
03542 CONNECTION_LOCK (connection);
03543
03544 _dbus_assert (message == connection->message_borrowed);
03545
03546 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03547 _dbus_assert (message == pop_message);
03548
03549 connection->n_incoming -= 1;
03550
03551 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03552 message, connection->n_incoming);
03553
03554 connection->message_borrowed = NULL;
03555
03556 _dbus_connection_release_dispatch (connection);
03557
03558 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03559 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03560 }
03561
03562
03563
03564
03565 static DBusList*
03566 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03567 {
03568 HAVE_LOCK_CHECK (connection);
03569
03570 _dbus_assert (connection->message_borrowed == NULL);
03571
03572 if (connection->n_incoming > 0)
03573 {
03574 DBusList *link;
03575
03576 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03577 connection->n_incoming -= 1;
03578
03579 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03580 link->data,
03581 dbus_message_get_type (link->data),
03582 dbus_message_get_path (link->data) ?
03583 dbus_message_get_path (link->data) :
03584 "no path",
03585 dbus_message_get_interface (link->data) ?
03586 dbus_message_get_interface (link->data) :
03587 "no interface",
03588 dbus_message_get_member (link->data) ?
03589 dbus_message_get_member (link->data) :
03590 "no member",
03591 dbus_message_get_signature (link->data),
03592 connection, connection->n_incoming);
03593
03594 check_disconnected_message_arrived_unlocked (connection, link->data);
03595
03596 return link;
03597 }
03598 else
03599 return NULL;
03600 }
03601
03602
03603
03604
03605 static DBusMessage*
03606 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03607 {
03608 DBusList *link;
03609
03610 HAVE_LOCK_CHECK (connection);
03611
03612 link = _dbus_connection_pop_message_link_unlocked (connection);
03613
03614 if (link != NULL)
03615 {
03616 DBusMessage *message;
03617
03618 message = link->data;
03619
03620 _dbus_list_free_link (link);
03621
03622 return message;
03623 }
03624 else
03625 return NULL;
03626 }
03627
03628 static void
03629 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03630 DBusList *message_link)
03631 {
03632 HAVE_LOCK_CHECK (connection);
03633
03634 _dbus_assert (message_link != NULL);
03635
03636 _dbus_assert (connection->message_borrowed == NULL);
03637
03638 _dbus_assert (connection->dispatch_acquired);
03639
03640 _dbus_list_prepend_link (&connection->incoming_messages,
03641 message_link);
03642 connection->n_incoming += 1;
03643
03644 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03645 message_link->data,
03646 dbus_message_get_type (message_link->data),
03647 dbus_message_get_interface (message_link->data) ?
03648 dbus_message_get_interface (message_link->data) :
03649 "no interface",
03650 dbus_message_get_member (message_link->data) ?
03651 dbus_message_get_member (message_link->data) :
03652 "no member",
03653 dbus_message_get_signature (message_link->data),
03654 connection, connection->n_incoming);
03655 }
03656
03676 DBusMessage*
03677 dbus_connection_pop_message (DBusConnection *connection)
03678 {
03679 DBusMessage *message;
03680 DBusDispatchStatus status;
03681
03682 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03683
03684
03685
03686
03687 status = dbus_connection_get_dispatch_status (connection);
03688 if (status != DBUS_DISPATCH_DATA_REMAINS)
03689 return NULL;
03690
03691 CONNECTION_LOCK (connection);
03692 _dbus_connection_acquire_dispatch (connection);
03693 HAVE_LOCK_CHECK (connection);
03694
03695 message = _dbus_connection_pop_message_unlocked (connection);
03696
03697 _dbus_verbose ("Returning popped message %p\n", message);
03698
03699 _dbus_connection_release_dispatch (connection);
03700
03701 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03702 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03703
03704 return message;
03705 }
03706
03714 static void
03715 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03716 {
03717 HAVE_LOCK_CHECK (connection);
03718
03719 _dbus_connection_ref_unlocked (connection);
03720 CONNECTION_UNLOCK (connection);
03721
03722 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03723 _dbus_mutex_lock (connection->dispatch_mutex);
03724
03725 while (connection->dispatch_acquired)
03726 {
03727 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03728 _dbus_condvar_wait (connection->dispatch_cond,
03729 connection->dispatch_mutex);
03730 }
03731
03732 _dbus_assert (!connection->dispatch_acquired);
03733
03734 connection->dispatch_acquired = TRUE;
03735
03736 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03737 _dbus_mutex_unlock (connection->dispatch_mutex);
03738
03739 CONNECTION_LOCK (connection);
03740 _dbus_connection_unref_unlocked (connection);
03741 }
03742
03750 static void
03751 _dbus_connection_release_dispatch (DBusConnection *connection)
03752 {
03753 HAVE_LOCK_CHECK (connection);
03754
03755 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03756 _dbus_mutex_lock (connection->dispatch_mutex);
03757
03758 _dbus_assert (connection->dispatch_acquired);
03759
03760 connection->dispatch_acquired = FALSE;
03761 _dbus_condvar_wake_one (connection->dispatch_cond);
03762
03763 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03764 _dbus_mutex_unlock (connection->dispatch_mutex);
03765 }
03766
03767 static void
03768 _dbus_connection_failed_pop (DBusConnection *connection,
03769 DBusList *message_link)
03770 {
03771 _dbus_list_prepend_link (&connection->incoming_messages,
03772 message_link);
03773 connection->n_incoming += 1;
03774 }
03775
03776
03777 static void
03778 notify_disconnected_unlocked (DBusConnection *connection)
03779 {
03780 HAVE_LOCK_CHECK (connection);
03781
03782
03783
03784
03785
03786
03787
03788 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03789
03790
03791
03792
03793
03794 if (connection->n_outgoing > 0)
03795 {
03796 DBusList *link;
03797
03798 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03799 connection->n_outgoing);
03800
03801 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03802 {
03803 _dbus_connection_message_sent (connection, link->data);
03804 }
03805 }
03806 }
03807
03808
03809 static DBusDispatchStatus
03810 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03811 {
03812 HAVE_LOCK_CHECK (connection);
03813
03814 if (connection->disconnect_message_link != NULL)
03815 {
03816 _dbus_verbose ("Sending disconnect message from %s\n",
03817 _DBUS_FUNCTION_NAME);
03818
03819
03820
03821
03822 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03823
03824
03825
03826
03827 _dbus_connection_queue_synthesized_message_link (connection,
03828 connection->disconnect_message_link);
03829 connection->disconnect_message_link = NULL;
03830
03831 return DBUS_DISPATCH_DATA_REMAINS;
03832 }
03833
03834 return DBUS_DISPATCH_COMPLETE;
03835 }
03836
03837 static DBusDispatchStatus
03838 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03839 {
03840 HAVE_LOCK_CHECK (connection);
03841
03842 if (connection->n_incoming > 0)
03843 return DBUS_DISPATCH_DATA_REMAINS;
03844 else if (!_dbus_transport_queue_messages (connection->transport))
03845 return DBUS_DISPATCH_NEED_MEMORY;
03846 else
03847 {
03848 DBusDispatchStatus status;
03849 dbus_bool_t is_connected;
03850
03851 status = _dbus_transport_get_dispatch_status (connection->transport);
03852 is_connected = _dbus_transport_get_is_connected (connection->transport);
03853
03854 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03855 DISPATCH_STATUS_NAME (status), is_connected);
03856
03857 if (!is_connected)
03858 {
03859
03860
03861
03862
03863
03864
03865 notify_disconnected_unlocked (connection);
03866
03867
03868
03869
03870
03871
03872 if (status == DBUS_DISPATCH_COMPLETE)
03873 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
03874 }
03875
03876 if (status != DBUS_DISPATCH_COMPLETE)
03877 return status;
03878 else if (connection->n_incoming > 0)
03879 return DBUS_DISPATCH_DATA_REMAINS;
03880 else
03881 return DBUS_DISPATCH_COMPLETE;
03882 }
03883 }
03884
03885 static void
03886 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03887 DBusDispatchStatus new_status)
03888 {
03889 dbus_bool_t changed;
03890 DBusDispatchStatusFunction function;
03891 void *data;
03892
03893 HAVE_LOCK_CHECK (connection);
03894
03895 _dbus_connection_ref_unlocked (connection);
03896
03897 changed = new_status != connection->last_dispatch_status;
03898
03899 connection->last_dispatch_status = new_status;
03900
03901 function = connection->dispatch_status_function;
03902 data = connection->dispatch_status_data;
03903
03904 if (connection->disconnected_message_arrived &&
03905 !connection->disconnected_message_processed)
03906 {
03907 connection->disconnected_message_processed = TRUE;
03908
03909
03910
03911
03912
03913 connection_forget_shared_unlocked (connection);
03914
03915 if (connection->exit_on_disconnect)
03916 {
03917 CONNECTION_UNLOCK (connection);
03918
03919 _dbus_verbose ("Exiting on Disconnected signal\n");
03920 _dbus_exit (1);
03921 _dbus_assert_not_reached ("Call to exit() returned");
03922 }
03923 }
03924
03925
03926 CONNECTION_UNLOCK (connection);
03927
03928 if (changed && function)
03929 {
03930 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03931 connection, new_status,
03932 DISPATCH_STATUS_NAME (new_status));
03933 (* function) (connection, new_status, data);
03934 }
03935
03936 dbus_connection_unref (connection);
03937 }
03938
03964 DBusDispatchStatus
03965 dbus_connection_get_dispatch_status (DBusConnection *connection)
03966 {
03967 DBusDispatchStatus status;
03968
03969 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03970
03971 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03972
03973 CONNECTION_LOCK (connection);
03974
03975 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03976
03977 CONNECTION_UNLOCK (connection);
03978
03979 return status;
03980 }
03981
03985 static DBusHandlerResult
03986 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03987 DBusMessage *message)
03988 {
03989 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
03990 {
03991
03992 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03993 }
03994 else if (dbus_message_is_method_call (message,
03995 DBUS_INTERFACE_PEER,
03996 "Ping"))
03997 {
03998 DBusMessage *ret;
03999 dbus_bool_t sent;
04000
04001 ret = dbus_message_new_method_return (message);
04002 if (ret == NULL)
04003 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04004
04005 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04006
04007 dbus_message_unref (ret);
04008
04009 if (!sent)
04010 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04011
04012 return DBUS_HANDLER_RESULT_HANDLED;
04013 }
04014 else if (dbus_message_is_method_call (message,
04015 DBUS_INTERFACE_PEER,
04016 "GetMachineId"))
04017 {
04018 DBusMessage *ret;
04019 dbus_bool_t sent;
04020 DBusString uuid;
04021
04022 ret = dbus_message_new_method_return (message);
04023 if (ret == NULL)
04024 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04025
04026 sent = FALSE;
04027 _dbus_string_init (&uuid);
04028 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04029 {
04030 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04031 if (dbus_message_append_args (ret,
04032 DBUS_TYPE_STRING, &v_STRING,
04033 DBUS_TYPE_INVALID))
04034 {
04035 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04036 }
04037 }
04038 _dbus_string_free (&uuid);
04039
04040 dbus_message_unref (ret);
04041
04042 if (!sent)
04043 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04044
04045 return DBUS_HANDLER_RESULT_HANDLED;
04046 }
04047 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04048 {
04049
04050
04051
04052
04053
04054 DBusMessage *ret;
04055 dbus_bool_t sent;
04056
04057 ret = dbus_message_new_error (message,
04058 DBUS_ERROR_UNKNOWN_METHOD,
04059 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04060 if (ret == NULL)
04061 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04062
04063 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04064
04065 dbus_message_unref (ret);
04066
04067 if (!sent)
04068 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04069
04070 return DBUS_HANDLER_RESULT_HANDLED;
04071 }
04072 else
04073 {
04074 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04075 }
04076 }
04077
04084 static DBusHandlerResult
04085 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04086 DBusMessage *message)
04087 {
04088
04089
04090
04091 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04092 }
04093
04136 DBusDispatchStatus
04137 dbus_connection_dispatch (DBusConnection *connection)
04138 {
04139 DBusMessage *message;
04140 DBusList *link, *filter_list_copy, *message_link;
04141 DBusHandlerResult result;
04142 DBusPendingCall *pending;
04143 dbus_int32_t reply_serial;
04144 DBusDispatchStatus status;
04145
04146 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04147
04148 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04149
04150 CONNECTION_LOCK (connection);
04151 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04152 if (status != DBUS_DISPATCH_DATA_REMAINS)
04153 {
04154
04155 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04156 return status;
04157 }
04158
04159
04160
04161
04162 _dbus_connection_ref_unlocked (connection);
04163
04164 _dbus_connection_acquire_dispatch (connection);
04165 HAVE_LOCK_CHECK (connection);
04166
04167 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04168 if (message_link == NULL)
04169 {
04170
04171
04172 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04173
04174 _dbus_connection_release_dispatch (connection);
04175
04176 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04177
04178 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04179
04180 dbus_connection_unref (connection);
04181
04182 return status;
04183 }
04184
04185 message = message_link->data;
04186
04187 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04188 message,
04189 dbus_message_get_type (message),
04190 dbus_message_get_interface (message) ?
04191 dbus_message_get_interface (message) :
04192 "no interface",
04193 dbus_message_get_member (message) ?
04194 dbus_message_get_member (message) :
04195 "no member",
04196 dbus_message_get_signature (message));
04197
04198 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04199
04200
04201
04202
04203
04204
04205
04206
04207 reply_serial = dbus_message_get_reply_serial (message);
04208 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04209 reply_serial);
04210 if (pending)
04211 {
04212 _dbus_verbose ("Dispatching a pending reply\n");
04213 complete_pending_call_and_unlock (connection, pending, message);
04214 pending = NULL;
04215
04216 CONNECTION_LOCK (connection);
04217 _dbus_verbose ("pending call completed in dispatch\n");
04218 result = DBUS_HANDLER_RESULT_HANDLED;
04219 goto out;
04220 }
04221
04222 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04223 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04224 goto out;
04225
04226 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04227 {
04228 _dbus_connection_release_dispatch (connection);
04229 HAVE_LOCK_CHECK (connection);
04230
04231 _dbus_connection_failed_pop (connection, message_link);
04232
04233
04234 _dbus_connection_update_dispatch_status_and_unlock (connection,
04235 DBUS_DISPATCH_NEED_MEMORY);
04236
04237 if (pending)
04238 dbus_pending_call_unref (pending);
04239 dbus_connection_unref (connection);
04240
04241 return DBUS_DISPATCH_NEED_MEMORY;
04242 }
04243
04244 _dbus_list_foreach (&filter_list_copy,
04245 (DBusForeachFunction)_dbus_message_filter_ref,
04246 NULL);
04247
04248
04249
04250
04251 CONNECTION_UNLOCK (connection);
04252
04253 link = _dbus_list_get_first_link (&filter_list_copy);
04254 while (link != NULL)
04255 {
04256 DBusMessageFilter *filter = link->data;
04257 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04258
04259 if (filter->function == NULL)
04260 {
04261 _dbus_verbose (" filter was removed in a callback function\n");
04262 link = next;
04263 continue;
04264 }
04265
04266 _dbus_verbose (" running filter on message %p\n", message);
04267 result = (* filter->function) (connection, message, filter->user_data);
04268
04269 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04270 break;
04271
04272 link = next;
04273 }
04274
04275 _dbus_list_foreach (&filter_list_copy,
04276 (DBusForeachFunction)_dbus_message_filter_unref,
04277 NULL);
04278 _dbus_list_clear (&filter_list_copy);
04279
04280 CONNECTION_LOCK (connection);
04281
04282 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04283 {
04284 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04285 goto out;
04286 }
04287 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04288 {
04289 _dbus_verbose ("filter handled message in dispatch\n");
04290 goto out;
04291 }
04292
04293
04294
04295
04296 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
04297 message,
04298 dbus_message_get_type (message),
04299 dbus_message_get_interface (message) ?
04300 dbus_message_get_interface (message) :
04301 "no interface",
04302 dbus_message_get_member (message) ?
04303 dbus_message_get_member (message) :
04304 "no member",
04305 dbus_message_get_signature (message));
04306
04307 HAVE_LOCK_CHECK (connection);
04308 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04309 message);
04310
04311 CONNECTION_LOCK (connection);
04312
04313 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04314 {
04315 _dbus_verbose ("object tree handled message in dispatch\n");
04316 goto out;
04317 }
04318
04319 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04320 {
04321 DBusMessage *reply;
04322 DBusString str;
04323 DBusPreallocatedSend *preallocated;
04324
04325 _dbus_verbose (" sending error %s\n",
04326 DBUS_ERROR_UNKNOWN_METHOD);
04327
04328 if (!_dbus_string_init (&str))
04329 {
04330 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04331 _dbus_verbose ("no memory for error string in dispatch\n");
04332 goto out;
04333 }
04334
04335 if (!_dbus_string_append_printf (&str,
04336 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04337 dbus_message_get_member (message),
04338 dbus_message_get_signature (message),
04339 dbus_message_get_interface (message)))
04340 {
04341 _dbus_string_free (&str);
04342 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04343 _dbus_verbose ("no memory for error string in dispatch\n");
04344 goto out;
04345 }
04346
04347 reply = dbus_message_new_error (message,
04348 DBUS_ERROR_UNKNOWN_METHOD,
04349 _dbus_string_get_const_data (&str));
04350 _dbus_string_free (&str);
04351
04352 if (reply == NULL)
04353 {
04354 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04355 _dbus_verbose ("no memory for error reply in dispatch\n");
04356 goto out;
04357 }
04358
04359 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04360
04361 if (preallocated == NULL)
04362 {
04363 dbus_message_unref (reply);
04364 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04365 _dbus_verbose ("no memory for error send in dispatch\n");
04366 goto out;
04367 }
04368
04369 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04370 reply, NULL);
04371
04372 dbus_message_unref (reply);
04373
04374 result = DBUS_HANDLER_RESULT_HANDLED;
04375 }
04376
04377 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04378 dbus_message_get_type (message),
04379 dbus_message_get_interface (message) ?
04380 dbus_message_get_interface (message) :
04381 "no interface",
04382 dbus_message_get_member (message) ?
04383 dbus_message_get_member (message) :
04384 "no member",
04385 dbus_message_get_signature (message),
04386 connection);
04387
04388 out:
04389 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04390 {
04391 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04392
04393
04394
04395
04396
04397 _dbus_connection_putback_message_link_unlocked (connection,
04398 message_link);
04399 }
04400 else
04401 {
04402 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04403
04404 _dbus_list_free_link (message_link);
04405 dbus_message_unref (message);
04406
04407
04408 }
04409
04410 _dbus_connection_release_dispatch (connection);
04411 HAVE_LOCK_CHECK (connection);
04412
04413 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04414 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04415
04416
04417 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04418
04419 dbus_connection_unref (connection);
04420
04421 return status;
04422 }
04423
04482 dbus_bool_t
04483 dbus_connection_set_watch_functions (DBusConnection *connection,
04484 DBusAddWatchFunction add_function,
04485 DBusRemoveWatchFunction remove_function,
04486 DBusWatchToggledFunction toggled_function,
04487 void *data,
04488 DBusFreeFunction free_data_function)
04489 {
04490 dbus_bool_t retval;
04491 DBusWatchList *watches;
04492
04493 _dbus_return_val_if_fail (connection != NULL, FALSE);
04494
04495 CONNECTION_LOCK (connection);
04496
04497 #ifndef DBUS_DISABLE_CHECKS
04498 if (connection->watches == NULL)
04499 {
04500 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04501 _DBUS_FUNCTION_NAME);
04502 return FALSE;
04503 }
04504 #endif
04505
04506
04507 _dbus_connection_ref_unlocked (connection);
04508
04509
04510
04511
04512
04513 watches = connection->watches;
04514 connection->watches = NULL;
04515 CONNECTION_UNLOCK (connection);
04516
04517 retval = _dbus_watch_list_set_functions (watches,
04518 add_function, remove_function,
04519 toggled_function,
04520 data, free_data_function);
04521 CONNECTION_LOCK (connection);
04522 connection->watches = watches;
04523
04524 CONNECTION_UNLOCK (connection);
04525
04526 dbus_connection_unref (connection);
04527
04528 return retval;
04529 }
04530
04564 dbus_bool_t
04565 dbus_connection_set_timeout_functions (DBusConnection *connection,
04566 DBusAddTimeoutFunction add_function,
04567 DBusRemoveTimeoutFunction remove_function,
04568 DBusTimeoutToggledFunction toggled_function,
04569 void *data,
04570 DBusFreeFunction free_data_function)
04571 {
04572 dbus_bool_t retval;
04573 DBusTimeoutList *timeouts;
04574
04575 _dbus_return_val_if_fail (connection != NULL, FALSE);
04576
04577 CONNECTION_LOCK (connection);
04578
04579 #ifndef DBUS_DISABLE_CHECKS
04580 if (connection->timeouts == NULL)
04581 {
04582 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04583 _DBUS_FUNCTION_NAME);
04584 return FALSE;
04585 }
04586 #endif
04587
04588
04589 _dbus_connection_ref_unlocked (connection);
04590
04591 timeouts = connection->timeouts;
04592 connection->timeouts = NULL;
04593 CONNECTION_UNLOCK (connection);
04594
04595 retval = _dbus_timeout_list_set_functions (timeouts,
04596 add_function, remove_function,
04597 toggled_function,
04598 data, free_data_function);
04599 CONNECTION_LOCK (connection);
04600 connection->timeouts = timeouts;
04601
04602 CONNECTION_UNLOCK (connection);
04603
04604 dbus_connection_unref (connection);
04605
04606 return retval;
04607 }
04608
04623 void
04624 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04625 DBusWakeupMainFunction wakeup_main_function,
04626 void *data,
04627 DBusFreeFunction free_data_function)
04628 {
04629 void *old_data;
04630 DBusFreeFunction old_free_data;
04631
04632 _dbus_return_if_fail (connection != NULL);
04633
04634 CONNECTION_LOCK (connection);
04635 old_data = connection->wakeup_main_data;
04636 old_free_data = connection->free_wakeup_main_data;
04637
04638 connection->wakeup_main_function = wakeup_main_function;
04639 connection->wakeup_main_data = data;
04640 connection->free_wakeup_main_data = free_data_function;
04641
04642 CONNECTION_UNLOCK (connection);
04643
04644
04645 if (old_free_data)
04646 (*old_free_data) (old_data);
04647 }
04648
04669 void
04670 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04671 DBusDispatchStatusFunction function,
04672 void *data,
04673 DBusFreeFunction free_data_function)
04674 {
04675 void *old_data;
04676 DBusFreeFunction old_free_data;
04677
04678 _dbus_return_if_fail (connection != NULL);
04679
04680 CONNECTION_LOCK (connection);
04681 old_data = connection->dispatch_status_data;
04682 old_free_data = connection->free_dispatch_status_data;
04683
04684 connection->dispatch_status_function = function;
04685 connection->dispatch_status_data = data;
04686 connection->free_dispatch_status_data = free_data_function;
04687
04688 CONNECTION_UNLOCK (connection);
04689
04690
04691 if (old_free_data)
04692 (*old_free_data) (old_data);
04693 }
04694
04714 dbus_bool_t
04715 dbus_connection_get_unix_fd (DBusConnection *connection,
04716 int *fd)
04717 {
04718 _dbus_return_val_if_fail (connection != NULL, FALSE);
04719 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04720
04721 #ifdef DBUS_WIN
04722
04723 return FALSE;
04724 #endif
04725
04726 return dbus_connection_get_socket(connection, fd);
04727 }
04728
04744 dbus_bool_t
04745 dbus_connection_get_socket(DBusConnection *connection,
04746 int *fd)
04747 {
04748 dbus_bool_t retval;
04749
04750 _dbus_return_val_if_fail (connection != NULL, FALSE);
04751 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04752
04753 CONNECTION_LOCK (connection);
04754
04755 retval = _dbus_transport_get_socket_fd (connection->transport,
04756 fd);
04757
04758 CONNECTION_UNLOCK (connection);
04759
04760 return retval;
04761 }
04762
04763
04784 dbus_bool_t
04785 dbus_connection_get_unix_user (DBusConnection *connection,
04786 unsigned long *uid)
04787 {
04788 dbus_bool_t result;
04789
04790 _dbus_return_val_if_fail (connection != NULL, FALSE);
04791 _dbus_return_val_if_fail (uid != NULL, FALSE);
04792
04793 #ifdef DBUS_WIN
04794
04795
04796
04797
04798 return FALSE;
04799 #endif
04800
04801 CONNECTION_LOCK (connection);
04802
04803 if (!_dbus_transport_get_is_authenticated (connection->transport))
04804 result = FALSE;
04805 else
04806 result = _dbus_transport_get_unix_user (connection->transport,
04807 uid);
04808 CONNECTION_UNLOCK (connection);
04809
04810 return result;
04811 }
04812
04823 dbus_bool_t
04824 dbus_connection_get_unix_process_id (DBusConnection *connection,
04825 unsigned long *pid)
04826 {
04827 dbus_bool_t result;
04828
04829 _dbus_return_val_if_fail (connection != NULL, FALSE);
04830 _dbus_return_val_if_fail (pid != NULL, FALSE);
04831
04832 #ifdef DBUS_WIN
04833
04834
04835
04836
04837 return FALSE;
04838 #endif
04839
04840 CONNECTION_LOCK (connection);
04841
04842 if (!_dbus_transport_get_is_authenticated (connection->transport))
04843 result = FALSE;
04844 else
04845 result = _dbus_transport_get_unix_process_id (connection->transport,
04846 pid);
04847 CONNECTION_UNLOCK (connection);
04848
04849 return result;
04850 }
04851
04875 void
04876 dbus_connection_set_unix_user_function (DBusConnection *connection,
04877 DBusAllowUnixUserFunction function,
04878 void *data,
04879 DBusFreeFunction free_data_function)
04880 {
04881 void *old_data = NULL;
04882 DBusFreeFunction old_free_function = NULL;
04883
04884 _dbus_return_if_fail (connection != NULL);
04885
04886 CONNECTION_LOCK (connection);
04887 _dbus_transport_set_unix_user_function (connection->transport,
04888 function, data, free_data_function,
04889 &old_data, &old_free_function);
04890 CONNECTION_UNLOCK (connection);
04891
04892 if (old_free_function != NULL)
04893 (* old_free_function) (old_data);
04894 }
04895
04914 void
04915 dbus_connection_set_route_peer_messages (DBusConnection *connection,
04916 dbus_bool_t value)
04917 {
04918 _dbus_return_if_fail (connection != NULL);
04919
04920 CONNECTION_LOCK (connection);
04921 connection->route_peer_messages = TRUE;
04922 CONNECTION_UNLOCK (connection);
04923 }
04924
04946 dbus_bool_t
04947 dbus_connection_add_filter (DBusConnection *connection,
04948 DBusHandleMessageFunction function,
04949 void *user_data,
04950 DBusFreeFunction free_data_function)
04951 {
04952 DBusMessageFilter *filter;
04953
04954 _dbus_return_val_if_fail (connection != NULL, FALSE);
04955 _dbus_return_val_if_fail (function != NULL, FALSE);
04956
04957 filter = dbus_new0 (DBusMessageFilter, 1);
04958 if (filter == NULL)
04959 return FALSE;
04960
04961 filter->refcount.value = 1;
04962
04963 CONNECTION_LOCK (connection);
04964
04965 if (!_dbus_list_append (&connection->filter_list,
04966 filter))
04967 {
04968 _dbus_message_filter_unref (filter);
04969 CONNECTION_UNLOCK (connection);
04970 return FALSE;
04971 }
04972
04973
04974
04975
04976
04977
04978 filter->function = function;
04979 filter->user_data = user_data;
04980 filter->free_user_data_function = free_data_function;
04981
04982 CONNECTION_UNLOCK (connection);
04983 return TRUE;
04984 }
04985
04998 void
04999 dbus_connection_remove_filter (DBusConnection *connection,
05000 DBusHandleMessageFunction function,
05001 void *user_data)
05002 {
05003 DBusList *link;
05004 DBusMessageFilter *filter;
05005
05006 _dbus_return_if_fail (connection != NULL);
05007 _dbus_return_if_fail (function != NULL);
05008
05009 CONNECTION_LOCK (connection);
05010
05011 filter = NULL;
05012
05013 link = _dbus_list_get_last_link (&connection->filter_list);
05014 while (link != NULL)
05015 {
05016 filter = link->data;
05017
05018 if (filter->function == function &&
05019 filter->user_data == user_data)
05020 {
05021 _dbus_list_remove_link (&connection->filter_list, link);
05022 filter->function = NULL;
05023
05024 break;
05025 }
05026
05027 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05028 }
05029
05030 CONNECTION_UNLOCK (connection);
05031
05032 #ifndef DBUS_DISABLE_CHECKS
05033 if (filter == NULL)
05034 {
05035 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05036 function, user_data);
05037 return;
05038 }
05039 #endif
05040
05041
05042 if (filter->free_user_data_function)
05043 (* filter->free_user_data_function) (filter->user_data);
05044
05045 filter->free_user_data_function = NULL;
05046 filter->user_data = NULL;
05047
05048 _dbus_message_filter_unref (filter);
05049 }
05050
05062 dbus_bool_t
05063 dbus_connection_register_object_path (DBusConnection *connection,
05064 const char *path,
05065 const DBusObjectPathVTable *vtable,
05066 void *user_data)
05067 {
05068 char **decomposed_path;
05069 dbus_bool_t retval;
05070
05071 _dbus_return_val_if_fail (connection != NULL, FALSE);
05072 _dbus_return_val_if_fail (path != NULL, FALSE);
05073 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05074 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05075
05076 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05077 return FALSE;
05078
05079 CONNECTION_LOCK (connection);
05080
05081 retval = _dbus_object_tree_register (connection->objects,
05082 FALSE,
05083 (const char **) decomposed_path, vtable,
05084 user_data);
05085
05086 CONNECTION_UNLOCK (connection);
05087
05088 dbus_free_string_array (decomposed_path);
05089
05090 return retval;
05091 }
05092
05105 dbus_bool_t
05106 dbus_connection_register_fallback (DBusConnection *connection,
05107 const char *path,
05108 const DBusObjectPathVTable *vtable,
05109 void *user_data)
05110 {
05111 char **decomposed_path;
05112 dbus_bool_t retval;
05113
05114 _dbus_return_val_if_fail (connection != NULL, FALSE);
05115 _dbus_return_val_if_fail (path != NULL, FALSE);
05116 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05117 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05118
05119 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05120 return FALSE;
05121
05122 CONNECTION_LOCK (connection);
05123
05124 retval = _dbus_object_tree_register (connection->objects,
05125 TRUE,
05126 (const char **) decomposed_path, vtable,
05127 user_data);
05128
05129 CONNECTION_UNLOCK (connection);
05130
05131 dbus_free_string_array (decomposed_path);
05132
05133 return retval;
05134 }
05135
05145 dbus_bool_t
05146 dbus_connection_unregister_object_path (DBusConnection *connection,
05147 const char *path)
05148 {
05149 char **decomposed_path;
05150
05151 _dbus_return_val_if_fail (connection != NULL, FALSE);
05152 _dbus_return_val_if_fail (path != NULL, FALSE);
05153 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05154
05155 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05156 return FALSE;
05157
05158 CONNECTION_LOCK (connection);
05159
05160 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05161
05162 dbus_free_string_array (decomposed_path);
05163
05164 return TRUE;
05165 }
05166
05177 dbus_bool_t
05178 dbus_connection_get_object_path_data (DBusConnection *connection,
05179 const char *path,
05180 void **data_p)
05181 {
05182 char **decomposed_path;
05183
05184 _dbus_return_val_if_fail (connection != NULL, FALSE);
05185 _dbus_return_val_if_fail (path != NULL, FALSE);
05186 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05187
05188 *data_p = NULL;
05189
05190 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05191 return FALSE;
05192
05193 CONNECTION_LOCK (connection);
05194
05195 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05196
05197 CONNECTION_UNLOCK (connection);
05198
05199 dbus_free_string_array (decomposed_path);
05200
05201 return TRUE;
05202 }
05203
05214 dbus_bool_t
05215 dbus_connection_list_registered (DBusConnection *connection,
05216 const char *parent_path,
05217 char ***child_entries)
05218 {
05219 char **decomposed_path;
05220 dbus_bool_t retval;
05221 _dbus_return_val_if_fail (connection != NULL, FALSE);
05222 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05223 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05224 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05225
05226 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05227 return FALSE;
05228
05229 CONNECTION_LOCK (connection);
05230
05231 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05232 (const char **) decomposed_path,
05233 child_entries);
05234 dbus_free_string_array (decomposed_path);
05235
05236 return retval;
05237 }
05238
05239 static DBusDataSlotAllocator slot_allocator;
05240 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05241
05256 dbus_bool_t
05257 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05258 {
05259 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05260 &_DBUS_LOCK_NAME (connection_slots),
05261 slot_p);
05262 }
05263
05275 void
05276 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05277 {
05278 _dbus_return_if_fail (*slot_p >= 0);
05279
05280 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05281 }
05282
05296 dbus_bool_t
05297 dbus_connection_set_data (DBusConnection *connection,
05298 dbus_int32_t slot,
05299 void *data,
05300 DBusFreeFunction free_data_func)
05301 {
05302 DBusFreeFunction old_free_func;
05303 void *old_data;
05304 dbus_bool_t retval;
05305
05306 _dbus_return_val_if_fail (connection != NULL, FALSE);
05307 _dbus_return_val_if_fail (slot >= 0, FALSE);
05308
05309 CONNECTION_LOCK (connection);
05310
05311 retval = _dbus_data_slot_list_set (&slot_allocator,
05312 &connection->slot_list,
05313 slot, data, free_data_func,
05314 &old_free_func, &old_data);
05315
05316 CONNECTION_UNLOCK (connection);
05317
05318 if (retval)
05319 {
05320
05321 if (old_free_func)
05322 (* old_free_func) (old_data);
05323 }
05324
05325 return retval;
05326 }
05327
05336 void*
05337 dbus_connection_get_data (DBusConnection *connection,
05338 dbus_int32_t slot)
05339 {
05340 void *res;
05341
05342 _dbus_return_val_if_fail (connection != NULL, NULL);
05343
05344 CONNECTION_LOCK (connection);
05345
05346 res = _dbus_data_slot_list_get (&slot_allocator,
05347 &connection->slot_list,
05348 slot);
05349
05350 CONNECTION_UNLOCK (connection);
05351
05352 return res;
05353 }
05354
05361 void
05362 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05363 {
05364 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05365 }
05366
05375 void
05376 dbus_connection_set_max_message_size (DBusConnection *connection,
05377 long size)
05378 {
05379 _dbus_return_if_fail (connection != NULL);
05380
05381 CONNECTION_LOCK (connection);
05382 _dbus_transport_set_max_message_size (connection->transport,
05383 size);
05384 CONNECTION_UNLOCK (connection);
05385 }
05386
05393 long
05394 dbus_connection_get_max_message_size (DBusConnection *connection)
05395 {
05396 long res;
05397
05398 _dbus_return_val_if_fail (connection != NULL, 0);
05399
05400 CONNECTION_LOCK (connection);
05401 res = _dbus_transport_get_max_message_size (connection->transport);
05402 CONNECTION_UNLOCK (connection);
05403 return res;
05404 }
05405
05431 void
05432 dbus_connection_set_max_received_size (DBusConnection *connection,
05433 long size)
05434 {
05435 _dbus_return_if_fail (connection != NULL);
05436
05437 CONNECTION_LOCK (connection);
05438 _dbus_transport_set_max_received_size (connection->transport,
05439 size);
05440 CONNECTION_UNLOCK (connection);
05441 }
05442
05449 long
05450 dbus_connection_get_max_received_size (DBusConnection *connection)
05451 {
05452 long res;
05453
05454 _dbus_return_val_if_fail (connection != NULL, 0);
05455
05456 CONNECTION_LOCK (connection);
05457 res = _dbus_transport_get_max_received_size (connection->transport);
05458 CONNECTION_UNLOCK (connection);
05459 return res;
05460 }
05461
05472 long
05473 dbus_connection_get_outgoing_size (DBusConnection *connection)
05474 {
05475 long res;
05476
05477 _dbus_return_val_if_fail (connection != NULL, 0);
05478
05479 CONNECTION_LOCK (connection);
05480 res = _dbus_counter_get_value (connection->outgoing_counter);
05481 CONNECTION_UNLOCK (connection);
05482 return res;
05483 }
05484
05517 char*
05518 dbus_get_local_machine_id (void)
05519 {
05520 DBusString uuid;
05521 char *s;
05522
05523 s = NULL;
05524 _dbus_string_init (&uuid);
05525 if (!_dbus_get_local_machine_uuid_encoded (&uuid) ||
05526 !_dbus_string_steal_data (&uuid, &s))
05527 {
05528 _dbus_string_free (&uuid);
05529 return FALSE;
05530 }
05531 else
05532 {
05533 _dbus_string_free (&uuid);
05534 return s;
05535 }
05536
05537 }
05538