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-list.h"
00033 #include "dbus-hash.h"
00034 #include "dbus-message-internal.h"
00035 #include "dbus-threads.h"
00036 #include "dbus-protocol.h"
00037 #include "dbus-dataslot.h"
00038 #include "dbus-string.h"
00039 #include "dbus-pending-call.h"
00040 #include "dbus-object-tree.h"
00041 #include "dbus-marshal.h"
00042
00043 #ifdef DBUS_DISABLE_CHECKS
00044 #define TOOK_LOCK_CHECK(connection)
00045 #define RELEASING_LOCK_CHECK(connection)
00046 #define HAVE_LOCK_CHECK(connection)
00047 #else
00048 #define TOOK_LOCK_CHECK(connection) do { \
00049 _dbus_assert (!(connection)->have_connection_lock); \
00050 (connection)->have_connection_lock = TRUE; \
00051 } while (0)
00052 #define RELEASING_LOCK_CHECK(connection) do { \
00053 _dbus_assert ((connection)->have_connection_lock); \
00054 (connection)->have_connection_lock = FALSE; \
00055 } while (0)
00056 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00057
00058 #endif
00059
00060 #define TRACE_LOCKS 1
00061
00062 #define CONNECTION_LOCK(connection) do { \
00063 if (TRACE_LOCKS) { _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00064 dbus_mutex_lock ((connection)->mutex); \
00065 TOOK_LOCK_CHECK (connection); \
00066 } while (0)
00067
00068 #define CONNECTION_UNLOCK(connection) do { \
00069 if (TRACE_LOCKS) { _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00070 RELEASING_LOCK_CHECK (connection); \
00071 dbus_mutex_unlock ((connection)->mutex); \
00072 } while (0)
00073
00074 #define DISPATCH_STATUS_NAME(s) \
00075 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00076 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00077 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00078 "???")
00079
00157 typedef struct DBusMessageFilter DBusMessageFilter;
00158
00162 struct DBusMessageFilter
00163 {
00164 DBusAtomic refcount;
00165 DBusHandleMessageFunction function;
00166 void *user_data;
00167 DBusFreeFunction free_user_data_function;
00168 };
00169
00170
00174 struct DBusPreallocatedSend
00175 {
00176 DBusConnection *connection;
00177 DBusList *queue_link;
00178 DBusList *counter_link;
00179 };
00180
00181 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00182
00186 struct DBusConnection
00187 {
00188 DBusAtomic refcount;
00190 DBusMutex *mutex;
00192 DBusMutex *dispatch_mutex;
00193 DBusCondVar *dispatch_cond;
00194 DBusMutex *io_path_mutex;
00195 DBusCondVar *io_path_cond;
00197 DBusList *outgoing_messages;
00198 DBusList *incoming_messages;
00200 DBusMessage *message_borrowed;
00204 int n_outgoing;
00205 int n_incoming;
00207 DBusCounter *outgoing_counter;
00209 DBusTransport *transport;
00210 DBusWatchList *watches;
00211 DBusTimeoutList *timeouts;
00213 DBusList *filter_list;
00215 DBusDataSlotList slot_list;
00217 DBusHashTable *pending_replies;
00219 dbus_uint32_t client_serial;
00220 DBusList *disconnect_message_link;
00222 DBusWakeupMainFunction wakeup_main_function;
00223 void *wakeup_main_data;
00224 DBusFreeFunction free_wakeup_main_data;
00226 DBusDispatchStatusFunction dispatch_status_function;
00227 void *dispatch_status_data;
00228 DBusFreeFunction free_dispatch_status_data;
00230 DBusDispatchStatus last_dispatch_status;
00232 DBusList *link_cache;
00235 DBusObjectTree *objects;
00237 unsigned int dispatch_acquired : 1;
00238 unsigned int io_path_acquired : 1;
00240 unsigned int exit_on_disconnect : 1;
00242 #ifndef DBUS_DISABLE_CHECKS
00243 unsigned int have_connection_lock : 1;
00244 #endif
00245
00246 #ifndef DBUS_DISABLE_CHECKS
00247 int generation;
00248 #endif
00249 };
00250
00251 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00252 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00253 DBusDispatchStatus new_status);
00254 static void _dbus_connection_last_unref (DBusConnection *connection);
00255 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00256 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00257
00258 static DBusMessageFilter *
00259 _dbus_message_filter_ref (DBusMessageFilter *filter)
00260 {
00261 _dbus_assert (filter->refcount.value > 0);
00262 _dbus_atomic_inc (&filter->refcount);
00263
00264 return filter;
00265 }
00266
00267 static void
00268 _dbus_message_filter_unref (DBusMessageFilter *filter)
00269 {
00270 _dbus_assert (filter->refcount.value > 0);
00271
00272 if (_dbus_atomic_dec (&filter->refcount) == 1)
00273 {
00274 if (filter->free_user_data_function)
00275 (* filter->free_user_data_function) (filter->user_data);
00276
00277 dbus_free (filter);
00278 }
00279 }
00280
00286 void
00287 _dbus_connection_lock (DBusConnection *connection)
00288 {
00289 CONNECTION_LOCK (connection);
00290 }
00291
00297 void
00298 _dbus_connection_unlock (DBusConnection *connection)
00299 {
00300 CONNECTION_UNLOCK (connection);
00301 }
00302
00310 static void
00311 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00312 {
00313 if (connection->wakeup_main_function)
00314 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00315 }
00316
00317 #ifdef DBUS_BUILD_TESTS
00318
00328 dbus_bool_t
00329 _dbus_connection_queue_received_message (DBusConnection *connection,
00330 DBusMessage *message)
00331 {
00332 DBusList *link;
00333
00334 link = _dbus_list_alloc_link (message);
00335 if (link == NULL)
00336 return FALSE;
00337
00338 dbus_message_ref (message);
00339 _dbus_connection_queue_received_message_link (connection, link);
00340
00341 return TRUE;
00342 }
00343 #endif
00344
00353 void
00354 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00355 DBusList *link)
00356 {
00357 DBusPendingCall *pending;
00358 dbus_int32_t reply_serial;
00359 DBusMessage *message;
00360
00361 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00362
00363 _dbus_list_append_link (&connection->incoming_messages,
00364 link);
00365 message = link->data;
00366
00367
00368 reply_serial = dbus_message_get_reply_serial (message);
00369 if (reply_serial != -1)
00370 {
00371 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00372 reply_serial);
00373 if (pending != NULL)
00374 {
00375 if (pending->timeout_added)
00376 _dbus_connection_remove_timeout (connection,
00377 pending->timeout);
00378
00379 pending->timeout_added = FALSE;
00380 }
00381 }
00382
00383 connection->n_incoming += 1;
00384
00385 _dbus_connection_wakeup_mainloop (connection);
00386
00387 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00388 message,
00389 dbus_message_get_type (message),
00390 dbus_message_get_path (message),
00391 dbus_message_get_interface (message) ?
00392 dbus_message_get_interface (message) :
00393 "no interface",
00394 dbus_message_get_member (message) ?
00395 dbus_message_get_member (message) :
00396 "no member",
00397 dbus_message_get_signature (message),
00398 dbus_message_get_reply_serial (message),
00399 connection,
00400 connection->n_incoming);
00401 }
00402
00413 static void
00414 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00415 DBusList *link)
00416 {
00417 HAVE_LOCK_CHECK (connection);
00418
00419 _dbus_list_append_link (&connection->incoming_messages, link);
00420
00421 connection->n_incoming += 1;
00422
00423 _dbus_connection_wakeup_mainloop (connection);
00424
00425 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00426 link->data, connection, connection->n_incoming);
00427 }
00428
00429
00437 dbus_bool_t
00438 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00439 {
00440 HAVE_LOCK_CHECK (connection);
00441 return connection->outgoing_messages != NULL;
00442 }
00443
00450 dbus_bool_t
00451 dbus_connection_has_messages_to_send (DBusConnection *connection)
00452 {
00453 dbus_bool_t v;
00454
00455 _dbus_return_val_if_fail (connection != NULL, FALSE);
00456
00457 CONNECTION_LOCK (connection);
00458 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00459 CONNECTION_UNLOCK (connection);
00460
00461 return v;
00462 }
00463
00471 DBusMessage*
00472 _dbus_connection_get_message_to_send (DBusConnection *connection)
00473 {
00474 HAVE_LOCK_CHECK (connection);
00475
00476 return _dbus_list_get_last (&connection->outgoing_messages);
00477 }
00478
00487 void
00488 _dbus_connection_message_sent (DBusConnection *connection,
00489 DBusMessage *message)
00490 {
00491 DBusList *link;
00492
00493 HAVE_LOCK_CHECK (connection);
00494
00495
00496
00497
00498
00499
00500 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00501 _dbus_assert (link != NULL);
00502 _dbus_assert (link->data == message);
00503
00504
00505 _dbus_list_unlink (&connection->outgoing_messages,
00506 link);
00507 _dbus_list_prepend_link (&connection->link_cache, link);
00508
00509 connection->n_outgoing -= 1;
00510
00511 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00512 message,
00513 dbus_message_get_type (message),
00514 dbus_message_get_path (message),
00515 dbus_message_get_interface (message) ?
00516 dbus_message_get_interface (message) :
00517 "no interface",
00518 dbus_message_get_member (message) ?
00519 dbus_message_get_member (message) :
00520 "no member",
00521 dbus_message_get_signature (message),
00522 connection, connection->n_outgoing);
00523
00524
00525 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00526 &link);
00527 _dbus_list_prepend_link (&connection->link_cache, link);
00528
00529 dbus_message_unref (message);
00530 }
00531
00532 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00533 DBusWatch *watch);
00534 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00535 DBusWatch *watch);
00536 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00537 DBusWatch *watch,
00538 dbus_bool_t enabled);
00539
00540 static dbus_bool_t
00541 protected_change_watch (DBusConnection *connection,
00542 DBusWatch *watch,
00543 DBusWatchAddFunction add_function,
00544 DBusWatchRemoveFunction remove_function,
00545 DBusWatchToggleFunction toggle_function,
00546 dbus_bool_t enabled)
00547 {
00548 DBusWatchList *watches;
00549 dbus_bool_t retval;
00550
00551 HAVE_LOCK_CHECK (connection);
00552
00553
00554
00555
00556
00557 watches = connection->watches;
00558 if (watches)
00559 {
00560 connection->watches = NULL;
00561 _dbus_connection_ref_unlocked (connection);
00562 CONNECTION_UNLOCK (connection);
00563
00564 if (add_function)
00565 retval = (* add_function) (watches, watch);
00566 else if (remove_function)
00567 {
00568 retval = TRUE;
00569 (* remove_function) (watches, watch);
00570 }
00571 else
00572 {
00573 retval = TRUE;
00574 (* toggle_function) (watches, watch, enabled);
00575 }
00576
00577 CONNECTION_LOCK (connection);
00578 connection->watches = watches;
00579 _dbus_connection_unref_unlocked (connection);
00580
00581 return retval;
00582 }
00583 else
00584 return FALSE;
00585 }
00586
00587
00598 dbus_bool_t
00599 _dbus_connection_add_watch (DBusConnection *connection,
00600 DBusWatch *watch)
00601 {
00602 return protected_change_watch (connection, watch,
00603 _dbus_watch_list_add_watch,
00604 NULL, NULL, FALSE);
00605 }
00606
00615 void
00616 _dbus_connection_remove_watch (DBusConnection *connection,
00617 DBusWatch *watch)
00618 {
00619 protected_change_watch (connection, watch,
00620 NULL,
00621 _dbus_watch_list_remove_watch,
00622 NULL, FALSE);
00623 }
00624
00635 void
00636 _dbus_connection_toggle_watch (DBusConnection *connection,
00637 DBusWatch *watch,
00638 dbus_bool_t enabled)
00639 {
00640 _dbus_assert (watch != NULL);
00641
00642 protected_change_watch (connection, watch,
00643 NULL, NULL,
00644 _dbus_watch_list_toggle_watch,
00645 enabled);
00646 }
00647
00648 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00649 DBusTimeout *timeout);
00650 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00651 DBusTimeout *timeout);
00652 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00653 DBusTimeout *timeout,
00654 dbus_bool_t enabled);
00655
00656 static dbus_bool_t
00657 protected_change_timeout (DBusConnection *connection,
00658 DBusTimeout *timeout,
00659 DBusTimeoutAddFunction add_function,
00660 DBusTimeoutRemoveFunction remove_function,
00661 DBusTimeoutToggleFunction toggle_function,
00662 dbus_bool_t enabled)
00663 {
00664 DBusTimeoutList *timeouts;
00665 dbus_bool_t retval;
00666
00667 HAVE_LOCK_CHECK (connection);
00668
00669
00670
00671
00672
00673 timeouts = connection->timeouts;
00674 if (timeouts)
00675 {
00676 connection->timeouts = NULL;
00677 _dbus_connection_ref_unlocked (connection);
00678 CONNECTION_UNLOCK (connection);
00679
00680 if (add_function)
00681 retval = (* add_function) (timeouts, timeout);
00682 else if (remove_function)
00683 {
00684 retval = TRUE;
00685 (* remove_function) (timeouts, timeout);
00686 }
00687 else
00688 {
00689 retval = TRUE;
00690 (* toggle_function) (timeouts, timeout, enabled);
00691 }
00692
00693 CONNECTION_LOCK (connection);
00694 connection->timeouts = timeouts;
00695 _dbus_connection_unref_unlocked (connection);
00696
00697 return retval;
00698 }
00699 else
00700 return FALSE;
00701 }
00702
00714 dbus_bool_t
00715 _dbus_connection_add_timeout (DBusConnection *connection,
00716 DBusTimeout *timeout)
00717 {
00718 return protected_change_timeout (connection, timeout,
00719 _dbus_timeout_list_add_timeout,
00720 NULL, NULL, FALSE);
00721 }
00722
00731 void
00732 _dbus_connection_remove_timeout (DBusConnection *connection,
00733 DBusTimeout *timeout)
00734 {
00735 protected_change_timeout (connection, timeout,
00736 NULL,
00737 _dbus_timeout_list_remove_timeout,
00738 NULL, FALSE);
00739 }
00740
00750 void
00751 _dbus_connection_toggle_timeout (DBusConnection *connection,
00752 DBusTimeout *timeout,
00753 dbus_bool_t enabled)
00754 {
00755 protected_change_timeout (connection, timeout,
00756 NULL, NULL,
00757 _dbus_timeout_list_toggle_timeout,
00758 enabled);
00759 }
00760
00761 static dbus_bool_t
00762 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00763 DBusPendingCall *pending)
00764 {
00765 HAVE_LOCK_CHECK (connection);
00766
00767 _dbus_assert (pending->reply_serial != 0);
00768
00769 if (!_dbus_connection_add_timeout (connection, pending->timeout))
00770 return FALSE;
00771
00772 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00773 pending->reply_serial,
00774 pending))
00775 {
00776 _dbus_connection_remove_timeout (connection, pending->timeout);
00777
00778 HAVE_LOCK_CHECK (connection);
00779 return FALSE;
00780 }
00781
00782 pending->timeout_added = TRUE;
00783 pending->connection = connection;
00784
00785 dbus_pending_call_ref (pending);
00786
00787 HAVE_LOCK_CHECK (connection);
00788
00789 return TRUE;
00790 }
00791
00792 static void
00793 free_pending_call_on_hash_removal (void *data)
00794 {
00795 DBusPendingCall *pending;
00796
00797 if (data == NULL)
00798 return;
00799
00800 pending = data;
00801
00802 if (pending->connection)
00803 {
00804 if (pending->timeout_added)
00805 {
00806 _dbus_connection_remove_timeout (pending->connection,
00807 pending->timeout);
00808 pending->timeout_added = FALSE;
00809 }
00810
00811 pending->connection = NULL;
00812
00813 dbus_pending_call_unref (pending);
00814 }
00815 }
00816
00817 static void
00818 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00819 DBusPendingCall *pending)
00820 {
00821
00822
00823 dbus_pending_call_ref (pending);
00824 _dbus_hash_table_remove_int (connection->pending_replies,
00825 pending->reply_serial);
00826 _dbus_assert (pending->connection == NULL);
00827 dbus_pending_call_unref (pending);
00828 }
00829
00830 static void
00831 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00832 DBusPendingCall *pending)
00833 {
00834
00835
00836
00837
00838 dbus_pending_call_ref (pending);
00839 _dbus_hash_table_remove_int (connection->pending_replies,
00840 pending->reply_serial);
00841 _dbus_assert (pending->connection == NULL);
00842 CONNECTION_UNLOCK (connection);
00843 dbus_pending_call_unref (pending);
00844 }
00845
00854 void
00855 _dbus_connection_remove_pending_call (DBusConnection *connection,
00856 DBusPendingCall *pending)
00857 {
00858 CONNECTION_LOCK (connection);
00859 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00860 }
00861
00870 void
00871 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00872 DBusMessage *message)
00873 {
00874 if (message == NULL)
00875 {
00876 message = pending->timeout_link->data;
00877 _dbus_list_clear (&pending->timeout_link);
00878 }
00879 else
00880 dbus_message_ref (message);
00881
00882 _dbus_verbose (" handing message %p (%s) to pending call serial %u\n",
00883 message,
00884 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00885 "method return" :
00886 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00887 "error" : "other type",
00888 pending->reply_serial);
00889
00890 _dbus_assert (pending->reply == NULL);
00891 _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00892 pending->reply = message;
00893
00894 dbus_pending_call_ref (pending);
00895 _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00896
00897
00898 _dbus_pending_call_notify (pending);
00899 dbus_pending_call_unref (pending);
00900 }
00901
00911 static dbus_bool_t
00912 _dbus_connection_acquire_io_path (DBusConnection *connection,
00913 int timeout_milliseconds)
00914 {
00915 dbus_bool_t we_acquired;
00916
00917 HAVE_LOCK_CHECK (connection);
00918
00919
00920 _dbus_connection_ref_unlocked (connection);
00921
00922
00923 CONNECTION_UNLOCK (connection);
00924
00925 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00926 dbus_mutex_lock (connection->io_path_mutex);
00927
00928 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00929 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00930
00931 we_acquired = FALSE;
00932
00933 if (connection->io_path_acquired)
00934 {
00935 if (timeout_milliseconds != -1)
00936 {
00937 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00938 _DBUS_FUNCTION_NAME, timeout_milliseconds);
00939 dbus_condvar_wait_timeout (connection->io_path_cond,
00940 connection->io_path_mutex,
00941 timeout_milliseconds);
00942 }
00943 else
00944 {
00945 while (connection->io_path_acquired)
00946 {
00947 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00948 dbus_condvar_wait (connection->io_path_cond, connection->io_path_mutex);
00949 }
00950 }
00951 }
00952
00953 if (!connection->io_path_acquired)
00954 {
00955 we_acquired = TRUE;
00956 connection->io_path_acquired = TRUE;
00957 }
00958
00959 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00960 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00961
00962 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00963 dbus_mutex_unlock (connection->io_path_mutex);
00964
00965 CONNECTION_LOCK (connection);
00966
00967 HAVE_LOCK_CHECK (connection);
00968
00969 _dbus_connection_unref_unlocked (connection);
00970
00971 return we_acquired;
00972 }
00973
00981 static void
00982 _dbus_connection_release_io_path (DBusConnection *connection)
00983 {
00984 HAVE_LOCK_CHECK (connection);
00985
00986 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00987 dbus_mutex_lock (connection->io_path_mutex);
00988
00989 _dbus_assert (connection->io_path_acquired);
00990
00991 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
00992 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
00993
00994 connection->io_path_acquired = FALSE;
00995 dbus_condvar_wake_one (connection->io_path_cond);
00996
00997 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00998 dbus_mutex_unlock (connection->io_path_mutex);
00999 }
01000
01029 void
01030 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01031 unsigned int flags,
01032 int timeout_milliseconds)
01033 {
01034 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01035
01036 HAVE_LOCK_CHECK (connection);
01037
01038 if (connection->n_outgoing == 0)
01039 flags &= ~DBUS_ITERATION_DO_WRITING;
01040
01041 if (_dbus_connection_acquire_io_path (connection,
01042 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01043 {
01044 HAVE_LOCK_CHECK (connection);
01045
01046 _dbus_transport_do_iteration (connection->transport,
01047 flags, timeout_milliseconds);
01048 _dbus_connection_release_io_path (connection);
01049 }
01050
01051 HAVE_LOCK_CHECK (connection);
01052
01053 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01054 }
01055
01065 DBusConnection*
01066 _dbus_connection_new_for_transport (DBusTransport *transport)
01067 {
01068 DBusConnection *connection;
01069 DBusWatchList *watch_list;
01070 DBusTimeoutList *timeout_list;
01071 DBusHashTable *pending_replies;
01072 DBusMutex *mutex;
01073 DBusMutex *io_path_mutex;
01074 DBusMutex *dispatch_mutex;
01075 DBusCondVar *message_returned_cond;
01076 DBusCondVar *dispatch_cond;
01077 DBusCondVar *io_path_cond;
01078 DBusList *disconnect_link;
01079 DBusMessage *disconnect_message;
01080 DBusCounter *outgoing_counter;
01081 DBusObjectTree *objects;
01082
01083 watch_list = NULL;
01084 connection = NULL;
01085 pending_replies = NULL;
01086 timeout_list = NULL;
01087 mutex = NULL;
01088 io_path_mutex = NULL;
01089 dispatch_mutex = NULL;
01090 message_returned_cond = NULL;
01091 dispatch_cond = NULL;
01092 io_path_cond = NULL;
01093 disconnect_link = NULL;
01094 disconnect_message = NULL;
01095 outgoing_counter = NULL;
01096 objects = NULL;
01097
01098 watch_list = _dbus_watch_list_new ();
01099 if (watch_list == NULL)
01100 goto error;
01101
01102 timeout_list = _dbus_timeout_list_new ();
01103 if (timeout_list == NULL)
01104 goto error;
01105
01106 pending_replies =
01107 _dbus_hash_table_new (DBUS_HASH_INT,
01108 NULL,
01109 (DBusFreeFunction)free_pending_call_on_hash_removal);
01110 if (pending_replies == NULL)
01111 goto error;
01112
01113 connection = dbus_new0 (DBusConnection, 1);
01114 if (connection == NULL)
01115 goto error;
01116
01117 mutex = dbus_mutex_new ();
01118 if (mutex == NULL)
01119 goto error;
01120
01121 io_path_mutex = dbus_mutex_new ();
01122 if (io_path_mutex == NULL)
01123 goto error;
01124
01125 dispatch_mutex = dbus_mutex_new ();
01126 if (dispatch_mutex == NULL)
01127 goto error;
01128
01129 message_returned_cond = dbus_condvar_new ();
01130 if (message_returned_cond == NULL)
01131 goto error;
01132
01133 dispatch_cond = dbus_condvar_new ();
01134 if (dispatch_cond == NULL)
01135 goto error;
01136
01137 io_path_cond = dbus_condvar_new ();
01138 if (io_path_cond == NULL)
01139 goto error;
01140
01141 disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL,
01142 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
01143 "Disconnected");
01144
01145 if (disconnect_message == NULL)
01146 goto error;
01147
01148 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01149 if (disconnect_link == NULL)
01150 goto error;
01151
01152 outgoing_counter = _dbus_counter_new ();
01153 if (outgoing_counter == NULL)
01154 goto error;
01155
01156 objects = _dbus_object_tree_new (connection);
01157 if (objects == NULL)
01158 goto error;
01159
01160 if (_dbus_modify_sigpipe)
01161 _dbus_disable_sigpipe ();
01162
01163 connection->refcount.value = 1;
01164 connection->mutex = mutex;
01165 connection->dispatch_cond = dispatch_cond;
01166 connection->dispatch_mutex = dispatch_mutex;
01167 connection->io_path_cond = io_path_cond;
01168 connection->io_path_mutex = io_path_mutex;
01169 connection->transport = transport;
01170 connection->watches = watch_list;
01171 connection->timeouts = timeout_list;
01172 connection->pending_replies = pending_replies;
01173 connection->outgoing_counter = outgoing_counter;
01174 connection->filter_list = NULL;
01175 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01176 connection->objects = objects;
01177 connection->exit_on_disconnect = FALSE;
01178 #ifndef DBUS_DISABLE_CHECKS
01179 connection->generation = _dbus_current_generation;
01180 #endif
01181
01182 _dbus_data_slot_list_init (&connection->slot_list);
01183
01184 connection->client_serial = 1;
01185
01186 connection->disconnect_message_link = disconnect_link;
01187
01188 CONNECTION_LOCK (connection);
01189
01190 if (!_dbus_transport_set_connection (transport, connection))
01191 goto error;
01192
01193 _dbus_transport_ref (transport);
01194
01195 CONNECTION_UNLOCK (connection);
01196
01197 return connection;
01198
01199 error:
01200 if (disconnect_message != NULL)
01201 dbus_message_unref (disconnect_message);
01202
01203 if (disconnect_link != NULL)
01204 _dbus_list_free_link (disconnect_link);
01205
01206 if (io_path_cond != NULL)
01207 dbus_condvar_free (io_path_cond);
01208
01209 if (dispatch_cond != NULL)
01210 dbus_condvar_free (dispatch_cond);
01211
01212 if (message_returned_cond != NULL)
01213 dbus_condvar_free (message_returned_cond);
01214
01215 if (mutex != NULL)
01216 dbus_mutex_free (mutex);
01217
01218 if (io_path_mutex != NULL)
01219 dbus_mutex_free (io_path_mutex);
01220
01221 if (dispatch_mutex != NULL)
01222 dbus_mutex_free (dispatch_mutex);
01223
01224 if (connection != NULL)
01225 dbus_free (connection);
01226
01227 if (pending_replies)
01228 _dbus_hash_table_unref (pending_replies);
01229
01230 if (watch_list)
01231 _dbus_watch_list_free (watch_list);
01232
01233 if (timeout_list)
01234 _dbus_timeout_list_free (timeout_list);
01235
01236 if (outgoing_counter)
01237 _dbus_counter_unref (outgoing_counter);
01238
01239 if (objects)
01240 _dbus_object_tree_unref (objects);
01241
01242 return NULL;
01243 }
01244
01252 DBusConnection *
01253 _dbus_connection_ref_unlocked (DBusConnection *connection)
01254 {
01255 _dbus_assert (connection != NULL);
01256 _dbus_assert (connection->generation == _dbus_current_generation);
01257
01258 HAVE_LOCK_CHECK (connection);
01259
01260 #ifdef DBUS_HAVE_ATOMIC_INT
01261 _dbus_atomic_inc (&connection->refcount);
01262 #else
01263 _dbus_assert (connection->refcount.value > 0);
01264 connection->refcount.value += 1;
01265 #endif
01266
01267 return connection;
01268 }
01269
01276 void
01277 _dbus_connection_unref_unlocked (DBusConnection *connection)
01278 {
01279 dbus_bool_t last_unref;
01280
01281 HAVE_LOCK_CHECK (connection);
01282
01283 _dbus_assert (connection != NULL);
01284
01285
01286
01287
01288
01289 #ifdef DBUS_HAVE_ATOMIC_INT
01290 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01291 #else
01292 _dbus_assert (connection->refcount.value > 0);
01293
01294 connection->refcount.value -= 1;
01295 last_unref = (connection->refcount.value == 0);
01296 #if 0
01297 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01298 #endif
01299 #endif
01300
01301 if (last_unref)
01302 _dbus_connection_last_unref (connection);
01303 }
01304
01305 static dbus_uint32_t
01306 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01307 {
01308 int serial;
01309
01310 serial = connection->client_serial++;
01311
01312 if (connection->client_serial < 0)
01313 connection->client_serial = 1;
01314
01315 return serial;
01316 }
01317
01331 dbus_bool_t
01332 _dbus_connection_handle_watch (DBusWatch *watch,
01333 unsigned int condition,
01334 void *data)
01335 {
01336 DBusConnection *connection;
01337 dbus_bool_t retval;
01338 DBusDispatchStatus status;
01339
01340 connection = data;
01341
01342 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01343
01344 CONNECTION_LOCK (connection);
01345 _dbus_connection_acquire_io_path (connection, -1);
01346 HAVE_LOCK_CHECK (connection);
01347 retval = _dbus_transport_handle_watch (connection->transport,
01348 watch, condition);
01349
01350 _dbus_connection_release_io_path (connection);
01351
01352 HAVE_LOCK_CHECK (connection);
01353
01354 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01355
01356 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01357
01358
01359 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01360
01361 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01362
01363 return retval;
01364 }
01365
01390 DBusConnection*
01391 dbus_connection_open (const char *address,
01392 DBusError *error)
01393 {
01394 DBusConnection *connection;
01395 DBusTransport *transport;
01396
01397 _dbus_return_val_if_fail (address != NULL, NULL);
01398 _dbus_return_val_if_error_is_set (error, NULL);
01399
01400 transport = _dbus_transport_open (address, error);
01401 if (transport == NULL)
01402 {
01403 _DBUS_ASSERT_ERROR_IS_SET (error);
01404 return NULL;
01405 }
01406
01407 connection = _dbus_connection_new_for_transport (transport);
01408
01409 _dbus_transport_unref (transport);
01410
01411 if (connection == NULL)
01412 {
01413 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01414 return NULL;
01415 }
01416
01417 #ifndef DBUS_DISABLE_CHECKS
01418 _dbus_assert (!connection->have_connection_lock);
01419 #endif
01420 return connection;
01421 }
01422
01429 DBusConnection *
01430 dbus_connection_ref (DBusConnection *connection)
01431 {
01432 _dbus_return_val_if_fail (connection != NULL, NULL);
01433 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01434
01435
01436
01437
01438
01439 #ifdef DBUS_HAVE_ATOMIC_INT
01440 _dbus_atomic_inc (&connection->refcount);
01441 #else
01442 CONNECTION_LOCK (connection);
01443 _dbus_assert (connection->refcount.value > 0);
01444
01445 connection->refcount.value += 1;
01446 CONNECTION_UNLOCK (connection);
01447 #endif
01448
01449 return connection;
01450 }
01451
01452 static void
01453 free_outgoing_message (void *element,
01454 void *data)
01455 {
01456 DBusMessage *message = element;
01457 DBusConnection *connection = data;
01458
01459 _dbus_message_remove_size_counter (message,
01460 connection->outgoing_counter,
01461 NULL);
01462 dbus_message_unref (message);
01463 }
01464
01465
01466
01467
01468
01469 static void
01470 _dbus_connection_last_unref (DBusConnection *connection)
01471 {
01472 DBusList *link;
01473
01474 _dbus_verbose ("Finalizing connection %p\n", connection);
01475
01476 _dbus_assert (connection->refcount.value == 0);
01477
01478
01479
01480
01481 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01482
01483
01484 _dbus_object_tree_free_all_unlocked (connection->objects);
01485
01486 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01487 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01488 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01489
01490 _dbus_watch_list_free (connection->watches);
01491 connection->watches = NULL;
01492
01493 _dbus_timeout_list_free (connection->timeouts);
01494 connection->timeouts = NULL;
01495
01496 _dbus_data_slot_list_free (&connection->slot_list);
01497
01498 link = _dbus_list_get_first_link (&connection->filter_list);
01499 while (link != NULL)
01500 {
01501 DBusMessageFilter *filter = link->data;
01502 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01503
01504 filter->function = NULL;
01505 _dbus_message_filter_unref (filter);
01506 link->data = NULL;
01507
01508 link = next;
01509 }
01510 _dbus_list_clear (&connection->filter_list);
01511
01512
01513
01514 _dbus_object_tree_unref (connection->objects);
01515
01516 _dbus_hash_table_unref (connection->pending_replies);
01517 connection->pending_replies = NULL;
01518
01519 _dbus_list_clear (&connection->filter_list);
01520
01521 _dbus_list_foreach (&connection->outgoing_messages,
01522 free_outgoing_message,
01523 connection);
01524 _dbus_list_clear (&connection->outgoing_messages);
01525
01526 _dbus_list_foreach (&connection->incoming_messages,
01527 (DBusForeachFunction) dbus_message_unref,
01528 NULL);
01529 _dbus_list_clear (&connection->incoming_messages);
01530
01531 _dbus_counter_unref (connection->outgoing_counter);
01532
01533 _dbus_transport_unref (connection->transport);
01534
01535 if (connection->disconnect_message_link)
01536 {
01537 DBusMessage *message = connection->disconnect_message_link->data;
01538 dbus_message_unref (message);
01539 _dbus_list_free_link (connection->disconnect_message_link);
01540 }
01541
01542 _dbus_list_clear (&connection->link_cache);
01543
01544 dbus_condvar_free (connection->dispatch_cond);
01545 dbus_condvar_free (connection->io_path_cond);
01546
01547 dbus_mutex_free (connection->io_path_mutex);
01548 dbus_mutex_free (connection->dispatch_mutex);
01549
01550 dbus_mutex_free (connection->mutex);
01551
01552 dbus_free (connection);
01553 }
01554
01566 void
01567 dbus_connection_unref (DBusConnection *connection)
01568 {
01569 dbus_bool_t last_unref;
01570
01571 _dbus_return_if_fail (connection != NULL);
01572 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01573
01574
01575
01576
01577
01578 #ifdef DBUS_HAVE_ATOMIC_INT
01579 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01580 #else
01581 CONNECTION_LOCK (connection);
01582
01583 _dbus_assert (connection->refcount.value > 0);
01584
01585 connection->refcount.value -= 1;
01586 last_unref = (connection->refcount.value == 0);
01587
01588 #if 0
01589 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01590 #endif
01591
01592 CONNECTION_UNLOCK (connection);
01593 #endif
01594
01595 if (last_unref)
01596 _dbus_connection_last_unref (connection);
01597 }
01598
01612 void
01613 dbus_connection_disconnect (DBusConnection *connection)
01614 {
01615 DBusDispatchStatus status;
01616
01617 _dbus_return_if_fail (connection != NULL);
01618 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01619
01620 _dbus_verbose ("Disconnecting %p\n", connection);
01621
01622 CONNECTION_LOCK (connection);
01623 _dbus_transport_disconnect (connection->transport);
01624
01625 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01626 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01627
01628
01629 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01630 }
01631
01632 static dbus_bool_t
01633 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01634 {
01635 HAVE_LOCK_CHECK (connection);
01636 return _dbus_transport_get_is_connected (connection->transport);
01637 }
01638
01649 dbus_bool_t
01650 dbus_connection_get_is_connected (DBusConnection *connection)
01651 {
01652 dbus_bool_t res;
01653
01654 _dbus_return_val_if_fail (connection != NULL, FALSE);
01655
01656 CONNECTION_LOCK (connection);
01657 res = _dbus_connection_get_is_connected_unlocked (connection);
01658 CONNECTION_UNLOCK (connection);
01659
01660 return res;
01661 }
01662
01671 dbus_bool_t
01672 dbus_connection_get_is_authenticated (DBusConnection *connection)
01673 {
01674 dbus_bool_t res;
01675
01676 _dbus_return_val_if_fail (connection != NULL, FALSE);
01677
01678 CONNECTION_LOCK (connection);
01679 res = _dbus_transport_get_is_authenticated (connection->transport);
01680 CONNECTION_UNLOCK (connection);
01681
01682 return res;
01683 }
01684
01698 void
01699 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
01700 dbus_bool_t exit_on_disconnect)
01701 {
01702 _dbus_return_if_fail (connection != NULL);
01703
01704 CONNECTION_LOCK (connection);
01705 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
01706 CONNECTION_UNLOCK (connection);
01707 }
01708
01709 static DBusPreallocatedSend*
01710 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01711 {
01712 DBusPreallocatedSend *preallocated;
01713
01714 HAVE_LOCK_CHECK (connection);
01715
01716 _dbus_assert (connection != NULL);
01717
01718 preallocated = dbus_new (DBusPreallocatedSend, 1);
01719 if (preallocated == NULL)
01720 return NULL;
01721
01722 if (connection->link_cache != NULL)
01723 {
01724 preallocated->queue_link =
01725 _dbus_list_pop_first_link (&connection->link_cache);
01726 preallocated->queue_link->data = NULL;
01727 }
01728 else
01729 {
01730 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01731 if (preallocated->queue_link == NULL)
01732 goto failed_0;
01733 }
01734
01735 if (connection->link_cache != NULL)
01736 {
01737 preallocated->counter_link =
01738 _dbus_list_pop_first_link (&connection->link_cache);
01739 preallocated->counter_link->data = connection->outgoing_counter;
01740 }
01741 else
01742 {
01743 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01744 if (preallocated->counter_link == NULL)
01745 goto failed_1;
01746 }
01747
01748 _dbus_counter_ref (preallocated->counter_link->data);
01749
01750 preallocated->connection = connection;
01751
01752 return preallocated;
01753
01754 failed_1:
01755 _dbus_list_free_link (preallocated->queue_link);
01756 failed_0:
01757 dbus_free (preallocated);
01758
01759 return NULL;
01760 }
01761
01771 DBusPreallocatedSend*
01772 dbus_connection_preallocate_send (DBusConnection *connection)
01773 {
01774 DBusPreallocatedSend *preallocated;
01775
01776 _dbus_return_val_if_fail (connection != NULL, NULL);
01777
01778 CONNECTION_LOCK (connection);
01779
01780 preallocated =
01781 _dbus_connection_preallocate_send_unlocked (connection);
01782
01783 CONNECTION_UNLOCK (connection);
01784
01785 return preallocated;
01786 }
01787
01797 void
01798 dbus_connection_free_preallocated_send (DBusConnection *connection,
01799 DBusPreallocatedSend *preallocated)
01800 {
01801 _dbus_return_if_fail (connection != NULL);
01802 _dbus_return_if_fail (preallocated != NULL);
01803 _dbus_return_if_fail (connection == preallocated->connection);
01804
01805 _dbus_list_free_link (preallocated->queue_link);
01806 _dbus_counter_unref (preallocated->counter_link->data);
01807 _dbus_list_free_link (preallocated->counter_link);
01808 dbus_free (preallocated);
01809 }
01810
01811
01812 static void
01813 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01814 DBusPreallocatedSend *preallocated,
01815 DBusMessage *message,
01816 dbus_uint32_t *client_serial)
01817 {
01818 dbus_uint32_t serial;
01819 const char *sig;
01820
01821 preallocated->queue_link->data = message;
01822 _dbus_list_prepend_link (&connection->outgoing_messages,
01823 preallocated->queue_link);
01824
01825 _dbus_message_add_size_counter_link (message,
01826 preallocated->counter_link);
01827
01828 dbus_free (preallocated);
01829 preallocated = NULL;
01830
01831 dbus_message_ref (message);
01832
01833 connection->n_outgoing += 1;
01834
01835 sig = dbus_message_get_signature (message);
01836
01837 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01838 message,
01839 dbus_message_get_type (message),
01840 dbus_message_get_path (message),
01841 dbus_message_get_interface (message) ?
01842 dbus_message_get_interface (message) :
01843 "no interface",
01844 dbus_message_get_member (message) ?
01845 dbus_message_get_member (message) :
01846 "no member",
01847 sig,
01848 dbus_message_get_destination (message) ?
01849 dbus_message_get_destination (message) :
01850 "null",
01851 connection,
01852 connection->n_outgoing);
01853
01854 if (dbus_message_get_serial (message) == 0)
01855 {
01856 serial = _dbus_connection_get_next_client_serial (connection);
01857 _dbus_message_set_serial (message, serial);
01858 if (client_serial)
01859 *client_serial = serial;
01860 }
01861 else
01862 {
01863 if (client_serial)
01864 *client_serial = dbus_message_get_serial (message);
01865 }
01866
01867 _dbus_verbose ("Message %p serial is %u\n",
01868 message, dbus_message_get_serial (message));
01869
01870 _dbus_message_lock (message);
01871
01872
01873
01874
01875 _dbus_connection_do_iteration_unlocked (connection,
01876 DBUS_ITERATION_DO_WRITING,
01877 -1);
01878
01879
01880 if (connection->n_outgoing > 0)
01881 _dbus_connection_wakeup_mainloop (connection);
01882 }
01883
01884 static void
01885 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
01886 DBusPreallocatedSend *preallocated,
01887 DBusMessage *message,
01888 dbus_uint32_t *client_serial)
01889 {
01890 DBusDispatchStatus status;
01891
01892 HAVE_LOCK_CHECK (connection);
01893
01894 _dbus_connection_send_preallocated_unlocked_no_update (connection,
01895 preallocated,
01896 message, client_serial);
01897
01898 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01899 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01900
01901
01902 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01903 }
01904
01917 void
01918 dbus_connection_send_preallocated (DBusConnection *connection,
01919 DBusPreallocatedSend *preallocated,
01920 DBusMessage *message,
01921 dbus_uint32_t *client_serial)
01922 {
01923 _dbus_return_if_fail (connection != NULL);
01924 _dbus_return_if_fail (preallocated != NULL);
01925 _dbus_return_if_fail (message != NULL);
01926 _dbus_return_if_fail (preallocated->connection == connection);
01927 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
01928 (dbus_message_get_interface (message) != NULL &&
01929 dbus_message_get_member (message) != NULL));
01930 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
01931 (dbus_message_get_interface (message) != NULL &&
01932 dbus_message_get_member (message) != NULL));
01933
01934 CONNECTION_LOCK (connection);
01935 _dbus_connection_send_preallocated_and_unlock (connection,
01936 preallocated,
01937 message, client_serial);
01938 }
01939
01940 static dbus_bool_t
01941 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
01942 DBusMessage *message,
01943 dbus_uint32_t *client_serial)
01944 {
01945 DBusPreallocatedSend *preallocated;
01946
01947 _dbus_assert (connection != NULL);
01948 _dbus_assert (message != NULL);
01949
01950 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01951 if (preallocated == NULL)
01952 return FALSE;
01953
01954 _dbus_connection_send_preallocated_unlocked_no_update (connection,
01955 preallocated,
01956 message,
01957 client_serial);
01958 return TRUE;
01959 }
01960
01961 dbus_bool_t
01962 _dbus_connection_send_and_unlock (DBusConnection *connection,
01963 DBusMessage *message,
01964 dbus_uint32_t *client_serial)
01965 {
01966 DBusPreallocatedSend *preallocated;
01967
01968 _dbus_assert (connection != NULL);
01969 _dbus_assert (message != NULL);
01970
01971 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01972 if (preallocated == NULL)
01973 {
01974 CONNECTION_UNLOCK (connection);
01975 return FALSE;
01976 }
01977
01978 _dbus_connection_send_preallocated_and_unlock (connection,
01979 preallocated,
01980 message,
01981 client_serial);
01982 return TRUE;
01983 }
01984
02003 dbus_bool_t
02004 dbus_connection_send (DBusConnection *connection,
02005 DBusMessage *message,
02006 dbus_uint32_t *client_serial)
02007 {
02008 _dbus_return_val_if_fail (connection != NULL, FALSE);
02009 _dbus_return_val_if_fail (message != NULL, FALSE);
02010
02011 CONNECTION_LOCK (connection);
02012
02013 return _dbus_connection_send_and_unlock (connection,
02014 message,
02015 client_serial);
02016 }
02017
02018 static dbus_bool_t
02019 reply_handler_timeout (void *data)
02020 {
02021 DBusConnection *connection;
02022 DBusDispatchStatus status;
02023 DBusPendingCall *pending = data;
02024
02025 connection = pending->connection;
02026
02027 CONNECTION_LOCK (connection);
02028 if (pending->timeout_link)
02029 {
02030 _dbus_connection_queue_synthesized_message_link (connection,
02031 pending->timeout_link);
02032 pending->timeout_link = NULL;
02033 }
02034
02035 _dbus_connection_remove_timeout (connection,
02036 pending->timeout);
02037 pending->timeout_added = FALSE;
02038
02039 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02040 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02041
02042
02043 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02044
02045 return TRUE;
02046 }
02047
02085 dbus_bool_t
02086 dbus_connection_send_with_reply (DBusConnection *connection,
02087 DBusMessage *message,
02088 DBusPendingCall **pending_return,
02089 int timeout_milliseconds)
02090 {
02091 DBusPendingCall *pending;
02092 DBusMessage *reply;
02093 DBusList *reply_link;
02094 dbus_int32_t serial = -1;
02095 DBusDispatchStatus status;
02096
02097 _dbus_return_val_if_fail (connection != NULL, FALSE);
02098 _dbus_return_val_if_fail (message != NULL, FALSE);
02099 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02100
02101 if (pending_return)
02102 *pending_return = NULL;
02103
02104 pending = _dbus_pending_call_new (connection,
02105 timeout_milliseconds,
02106 reply_handler_timeout);
02107
02108 if (pending == NULL)
02109 return FALSE;
02110
02111 CONNECTION_LOCK (connection);
02112
02113
02114 if (dbus_message_get_serial (message) == 0)
02115 {
02116 serial = _dbus_connection_get_next_client_serial (connection);
02117 _dbus_message_set_serial (message, serial);
02118 }
02119
02120 pending->reply_serial = serial;
02121
02122 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02123 "No reply within specified time");
02124 if (reply == NULL)
02125 goto error;
02126
02127 reply_link = _dbus_list_alloc_link (reply);
02128 if (reply_link == NULL)
02129 {
02130 CONNECTION_UNLOCK (connection);
02131 dbus_message_unref (reply);
02132 goto error_unlocked;
02133 }
02134
02135 pending->timeout_link = reply_link;
02136
02137
02138
02139
02140
02141 if (!_dbus_connection_attach_pending_call_unlocked (connection,
02142 pending))
02143 goto error;
02144
02145 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02146 {
02147 _dbus_connection_detach_pending_call_and_unlock (connection,
02148 pending);
02149 goto error_unlocked;
02150 }
02151
02152 if (pending_return)
02153 *pending_return = pending;
02154 else
02155 {
02156 _dbus_connection_detach_pending_call_unlocked (connection, pending);
02157 dbus_pending_call_unref (pending);
02158 }
02159
02160 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02161 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02162
02163
02164 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02165
02166 return TRUE;
02167
02168 error:
02169 CONNECTION_UNLOCK (connection);
02170 error_unlocked:
02171 dbus_pending_call_unref (pending);
02172 return FALSE;
02173 }
02174
02175
02176
02177
02178 static DBusMessage*
02179 check_for_reply_unlocked (DBusConnection *connection,
02180 dbus_uint32_t client_serial)
02181 {
02182 DBusList *link;
02183
02184 HAVE_LOCK_CHECK (connection);
02185
02186 link = _dbus_list_get_first_link (&connection->incoming_messages);
02187
02188 while (link != NULL)
02189 {
02190 DBusMessage *reply = link->data;
02191
02192 if (dbus_message_get_reply_serial (reply) == client_serial)
02193 {
02194 _dbus_list_remove_link (&connection->incoming_messages, link);
02195 connection->n_incoming -= 1;
02196 return reply;
02197 }
02198 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02199 }
02200
02201 return NULL;
02202 }
02203
02218 void
02219 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02220 {
02221 long start_tv_sec, start_tv_usec;
02222 long end_tv_sec, end_tv_usec;
02223 long tv_sec, tv_usec;
02224 DBusDispatchStatus status;
02225 DBusConnection *connection;
02226 dbus_uint32_t client_serial;
02227 int timeout_milliseconds;
02228
02229 _dbus_assert (pending != NULL);
02230
02231 if (dbus_pending_call_get_completed (pending))
02232 return;
02233
02234 if (pending->connection == NULL)
02235 return;
02236
02237 dbus_pending_call_ref (pending);
02238
02239 connection = pending->connection;
02240 client_serial = pending->reply_serial;
02241
02242
02243
02244
02245
02246 timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02247
02248
02249 dbus_connection_flush (connection);
02250
02251 CONNECTION_LOCK (connection);
02252
02253 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02254 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02255 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02256 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02257 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02258
02259 _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",
02260 timeout_milliseconds,
02261 client_serial,
02262 start_tv_sec, start_tv_usec,
02263 end_tv_sec, end_tv_usec);
02264
02265
02266
02267 _dbus_connection_do_iteration_unlocked (connection,
02268 DBUS_ITERATION_DO_READING |
02269 DBUS_ITERATION_BLOCK,
02270 timeout_milliseconds);
02271
02272 recheck_status:
02273
02274 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02275
02276 HAVE_LOCK_CHECK (connection);
02277
02278
02279
02280 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02281
02282
02283
02284
02285 if (dbus_pending_call_get_completed (pending))
02286 {
02287 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02288 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02289 dbus_pending_call_unref (pending);
02290 return;
02291 }
02292
02293 if (status == DBUS_DISPATCH_DATA_REMAINS)
02294 {
02295 DBusMessage *reply;
02296
02297 reply = check_for_reply_unlocked (connection, client_serial);
02298 if (reply != NULL)
02299 {
02300 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02301
02302 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02303
02304 _dbus_pending_call_complete_and_unlock (pending, reply);
02305 dbus_message_unref (reply);
02306
02307 CONNECTION_LOCK (connection);
02308 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02309 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02310 dbus_pending_call_unref (pending);
02311
02312 return;
02313 }
02314 }
02315
02316 _dbus_get_current_time (&tv_sec, &tv_usec);
02317
02318 if (!_dbus_connection_get_is_connected_unlocked (connection))
02319 {
02320
02321
02322
02323
02324
02325 _dbus_pending_call_complete_and_unlock (pending, NULL);
02326 dbus_pending_call_unref (pending);
02327 return;
02328 }
02329 else if (tv_sec < start_tv_sec)
02330 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02331 else if (connection->disconnect_message_link == NULL)
02332 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02333 else if (tv_sec < end_tv_sec ||
02334 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02335 {
02336 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02337 (end_tv_usec - tv_usec) / 1000;
02338 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02339 _dbus_assert (timeout_milliseconds >= 0);
02340
02341 if (status == DBUS_DISPATCH_NEED_MEMORY)
02342 {
02343
02344
02345
02346
02347 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02348
02349 if (timeout_milliseconds < 100)
02350 ;
02351 else if (timeout_milliseconds <= 1000)
02352 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02353 else
02354 _dbus_sleep_milliseconds (1000);
02355 }
02356 else
02357 {
02358
02359 _dbus_connection_do_iteration_unlocked (connection,
02360 DBUS_ITERATION_DO_READING |
02361 DBUS_ITERATION_BLOCK,
02362 timeout_milliseconds);
02363 }
02364
02365 goto recheck_status;
02366 }
02367
02368 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02369 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02370
02371 _dbus_assert (!dbus_pending_call_get_completed (pending));
02372
02373
02374 _dbus_pending_call_complete_and_unlock (pending, NULL);
02375
02376
02377 CONNECTION_LOCK (connection);
02378 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02379 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02380 dbus_pending_call_unref (pending);
02381 }
02382
02405 DBusMessage*
02406 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
02407 DBusMessage *message,
02408 int timeout_milliseconds,
02409 DBusError *error)
02410 {
02411 DBusMessage *reply;
02412 DBusPendingCall *pending;
02413
02414 _dbus_return_val_if_fail (connection != NULL, NULL);
02415 _dbus_return_val_if_fail (message != NULL, NULL);
02416 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02417 _dbus_return_val_if_error_is_set (error, NULL);
02418
02419 if (!dbus_connection_send_with_reply (connection, message,
02420 &pending, timeout_milliseconds))
02421 {
02422 _DBUS_SET_OOM (error);
02423 return NULL;
02424 }
02425
02426 _dbus_assert (pending != NULL);
02427
02428 dbus_pending_call_block (pending);
02429
02430 reply = dbus_pending_call_steal_reply (pending);
02431 dbus_pending_call_unref (pending);
02432
02433
02434
02435
02436 _dbus_assert (reply != NULL);
02437
02438 if (dbus_set_error_from_message (error, reply))
02439 {
02440 dbus_message_unref (reply);
02441 return NULL;
02442 }
02443 else
02444 return reply;
02445 }
02446
02452 void
02453 dbus_connection_flush (DBusConnection *connection)
02454 {
02455
02456
02457
02458
02459
02460 DBusDispatchStatus status;
02461
02462 _dbus_return_if_fail (connection != NULL);
02463
02464 CONNECTION_LOCK (connection);
02465 while (connection->n_outgoing > 0 &&
02466 _dbus_connection_get_is_connected_unlocked (connection))
02467 {
02468 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02469 HAVE_LOCK_CHECK (connection);
02470 _dbus_connection_do_iteration_unlocked (connection,
02471 DBUS_ITERATION_DO_READING |
02472 DBUS_ITERATION_DO_WRITING |
02473 DBUS_ITERATION_BLOCK,
02474 -1);
02475 }
02476
02477 HAVE_LOCK_CHECK (connection);
02478 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02479 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02480
02481 HAVE_LOCK_CHECK (connection);
02482
02483 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02484
02485 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02486 }
02487
02507 DBusMessage*
02508 dbus_connection_borrow_message (DBusConnection *connection)
02509 {
02510 DBusDispatchStatus status;
02511 DBusMessage *message;
02512
02513 _dbus_return_val_if_fail (connection != NULL, NULL);
02514
02515 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02516
02517
02518
02519
02520 status = dbus_connection_get_dispatch_status (connection);
02521 if (status != DBUS_DISPATCH_DATA_REMAINS)
02522 return NULL;
02523
02524 CONNECTION_LOCK (connection);
02525
02526 _dbus_connection_acquire_dispatch (connection);
02527
02528
02529 _dbus_assert (connection->message_borrowed == NULL);
02530
02531 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
02532
02533 message = connection->message_borrowed;
02534
02535