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-message-private.h"
00037 #include "dbus-threads.h"
00038 #include "dbus-protocol.h"
00039 #include "dbus-dataslot.h"
00040 #include "dbus-string.h"
00041 #include "dbus-signature.h"
00042 #include "dbus-pending-call.h"
00043 #include "dbus-object-tree.h"
00044 #include "dbus-threads-internal.h"
00045 #include "dbus-bus.h"
00046 #include "dbus-marshal-basic.h"
00047
00048 #ifdef DBUS_DISABLE_CHECKS
00049 #define TOOK_LOCK_CHECK(connection)
00050 #define RELEASING_LOCK_CHECK(connection)
00051 #define HAVE_LOCK_CHECK(connection)
00052 #else
00053 #define TOOK_LOCK_CHECK(connection) do { \
00054 _dbus_assert (!(connection)->have_connection_lock); \
00055 (connection)->have_connection_lock = TRUE; \
00056 } while (0)
00057 #define RELEASING_LOCK_CHECK(connection) do { \
00058 _dbus_assert ((connection)->have_connection_lock); \
00059 (connection)->have_connection_lock = FALSE; \
00060 } while (0)
00061 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00062
00063 #endif
00064
00065 #define TRACE_LOCKS 1
00066
00067 #define CONNECTION_LOCK(connection) do { \
00068 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
00069 _dbus_rmutex_lock ((connection)->mutex); \
00070 TOOK_LOCK_CHECK (connection); \
00071 } while (0)
00072
00073 #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
00074
00075 #define SLOTS_LOCK(connection) do { \
00076 _dbus_rmutex_lock ((connection)->slot_mutex); \
00077 } while (0)
00078
00079 #define SLOTS_UNLOCK(connection) do { \
00080 _dbus_rmutex_unlock ((connection)->slot_mutex); \
00081 } while (0)
00082
00083 #define DISPATCH_STATUS_NAME(s) \
00084 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00085 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00086 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00087 "???")
00088
00206 #ifdef DBUS_ENABLE_VERBOSE_MODE
00207 static void
00208 _dbus_connection_trace_ref (DBusConnection *connection,
00209 int old_refcount,
00210 int new_refcount,
00211 const char *why)
00212 {
00213 static int enabled = -1;
00214
00215 _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
00216 why, "DBUS_CONNECTION_TRACE", &enabled);
00217 }
00218 #else
00219 #define _dbus_connection_trace_ref(c,o,n,w) \
00220 do \
00221 {\
00222 (void) (o); \
00223 (void) (n); \
00224 } while (0)
00225 #endif
00226
00230 typedef struct DBusMessageFilter DBusMessageFilter;
00231
00235 struct DBusMessageFilter
00236 {
00237 DBusAtomic refcount;
00238 DBusHandleMessageFunction function;
00239 void *user_data;
00240 DBusFreeFunction free_user_data_function;
00241 };
00242
00243
00247 struct DBusPreallocatedSend
00248 {
00249 DBusConnection *connection;
00250 DBusList *queue_link;
00251 DBusList *counter_link;
00252 };
00253
00254 #if HAVE_DECL_MSG_NOSIGNAL
00255 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00256 #else
00257 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00258 #endif
00259
00263 struct DBusConnection
00264 {
00265 DBusAtomic refcount;
00267 DBusRMutex *mutex;
00269 DBusCMutex *dispatch_mutex;
00270 DBusCondVar *dispatch_cond;
00271 DBusCMutex *io_path_mutex;
00272 DBusCondVar *io_path_cond;
00274 DBusList *outgoing_messages;
00275 DBusList *incoming_messages;
00276 DBusList *expired_messages;
00278 DBusMessage *message_borrowed;
00282 int n_outgoing;
00283 int n_incoming;
00285 DBusCounter *outgoing_counter;
00287 DBusTransport *transport;
00288 DBusWatchList *watches;
00289 DBusTimeoutList *timeouts;
00291 DBusList *filter_list;
00293 DBusRMutex *slot_mutex;
00294 DBusDataSlotList slot_list;
00296 DBusHashTable *pending_replies;
00298 dbus_uint32_t client_serial;
00299 DBusList *disconnect_message_link;
00301 DBusWakeupMainFunction wakeup_main_function;
00302 void *wakeup_main_data;
00303 DBusFreeFunction free_wakeup_main_data;
00305 DBusDispatchStatusFunction dispatch_status_function;
00306 void *dispatch_status_data;
00307 DBusFreeFunction free_dispatch_status_data;
00309 DBusDispatchStatus last_dispatch_status;
00311 DBusObjectTree *objects;
00313 char *server_guid;
00315
00316
00317
00318
00319 dbus_bool_t dispatch_acquired;
00320 dbus_bool_t io_path_acquired;
00322 unsigned int shareable : 1;
00324 unsigned int exit_on_disconnect : 1;
00326 unsigned int route_peer_messages : 1;
00328 unsigned int disconnected_message_arrived : 1;
00332 unsigned int disconnected_message_processed : 1;
00336 #ifndef DBUS_DISABLE_CHECKS
00337 unsigned int have_connection_lock : 1;
00338 #endif
00339
00340 #ifndef DBUS_DISABLE_CHECKS
00341 int generation;
00342 #endif
00343 };
00344
00345 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00346 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00347 DBusDispatchStatus new_status);
00348 static void _dbus_connection_last_unref (DBusConnection *connection);
00349 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00350 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00351 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00352 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
00353 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
00354 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
00355 dbus_uint32_t client_serial);
00356
00357 static DBusMessageFilter *
00358 _dbus_message_filter_ref (DBusMessageFilter *filter)
00359 {
00360 #ifdef DBUS_DISABLE_ASSERT
00361 _dbus_atomic_inc (&filter->refcount);
00362 #else
00363 dbus_int32_t old_value;
00364
00365 old_value = _dbus_atomic_inc (&filter->refcount);
00366 _dbus_assert (old_value > 0);
00367 #endif
00368
00369 return filter;
00370 }
00371
00372 static void
00373 _dbus_message_filter_unref (DBusMessageFilter *filter)
00374 {
00375 dbus_int32_t old_value;
00376
00377 old_value = _dbus_atomic_dec (&filter->refcount);
00378 _dbus_assert (old_value > 0);
00379
00380 if (old_value == 1)
00381 {
00382 if (filter->free_user_data_function)
00383 (* filter->free_user_data_function) (filter->user_data);
00384
00385 dbus_free (filter);
00386 }
00387 }
00388
00394 void
00395 _dbus_connection_lock (DBusConnection *connection)
00396 {
00397 CONNECTION_LOCK (connection);
00398 }
00399
00405 void
00406 _dbus_connection_unlock (DBusConnection *connection)
00407 {
00408 DBusList *expired_messages;
00409 DBusList *iter;
00410
00411 if (TRACE_LOCKS)
00412 {
00413 _dbus_verbose ("UNLOCK\n");
00414 }
00415
00416
00417
00418 expired_messages = connection->expired_messages;
00419 connection->expired_messages = NULL;
00420
00421 RELEASING_LOCK_CHECK (connection);
00422 _dbus_rmutex_unlock (connection->mutex);
00423
00424 for (iter = _dbus_list_pop_first_link (&expired_messages);
00425 iter != NULL;
00426 iter = _dbus_list_pop_first_link (&expired_messages))
00427 {
00428 DBusMessage *message = iter->data;
00429
00430 dbus_message_unref (message);
00431 _dbus_list_free_link (iter);
00432 }
00433 }
00434
00442 static void
00443 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00444 {
00445 if (connection->wakeup_main_function)
00446 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00447 }
00448
00449 #ifdef DBUS_BUILD_TESTS
00450
00462 void
00463 _dbus_connection_test_get_locks (DBusConnection *connection,
00464 DBusMutex **mutex_loc,
00465 DBusMutex **dispatch_mutex_loc,
00466 DBusMutex **io_path_mutex_loc,
00467 DBusCondVar **dispatch_cond_loc,
00468 DBusCondVar **io_path_cond_loc)
00469 {
00470 *mutex_loc = (DBusMutex *) connection->mutex;
00471 *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
00472 *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
00473 *dispatch_cond_loc = connection->dispatch_cond;
00474 *io_path_cond_loc = connection->io_path_cond;
00475 }
00476 #endif
00477
00486 void
00487 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00488 DBusList *link)
00489 {
00490 DBusPendingCall *pending;
00491 dbus_uint32_t reply_serial;
00492 DBusMessage *message;
00493
00494 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00495
00496 _dbus_list_append_link (&connection->incoming_messages,
00497 link);
00498 message = link->data;
00499
00500
00501 reply_serial = dbus_message_get_reply_serial (message);
00502 if (reply_serial != 0)
00503 {
00504 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00505 reply_serial);
00506 if (pending != NULL)
00507 {
00508 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00509 _dbus_connection_remove_timeout_unlocked (connection,
00510 _dbus_pending_call_get_timeout_unlocked (pending));
00511
00512 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00513 }
00514 }
00515
00516
00517
00518 connection->n_incoming += 1;
00519
00520 _dbus_connection_wakeup_mainloop (connection);
00521
00522 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00523 message,
00524 dbus_message_type_to_string (dbus_message_get_type (message)),
00525 dbus_message_get_path (message) ?
00526 dbus_message_get_path (message) :
00527 "no path",
00528 dbus_message_get_interface (message) ?
00529 dbus_message_get_interface (message) :
00530 "no interface",
00531 dbus_message_get_member (message) ?
00532 dbus_message_get_member (message) :
00533 "no member",
00534 dbus_message_get_signature (message),
00535 dbus_message_get_reply_serial (message),
00536 connection,
00537 connection->n_incoming);
00538
00539 _dbus_message_trace_ref (message, -1, -1,
00540 "_dbus_conection_queue_received_message_link");
00541 }
00542
00551 void
00552 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00553 DBusList *link)
00554 {
00555 HAVE_LOCK_CHECK (connection);
00556
00557 _dbus_list_append_link (&connection->incoming_messages, link);
00558
00559 connection->n_incoming += 1;
00560
00561 _dbus_connection_wakeup_mainloop (connection);
00562
00563 _dbus_message_trace_ref (link->data, -1, -1,
00564 "_dbus_connection_queue_synthesized_message_link");
00565
00566 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00567 link->data, connection, connection->n_incoming);
00568 }
00569
00570
00578 dbus_bool_t
00579 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00580 {
00581 HAVE_LOCK_CHECK (connection);
00582 return connection->outgoing_messages != NULL;
00583 }
00584
00594 dbus_bool_t
00595 dbus_connection_has_messages_to_send (DBusConnection *connection)
00596 {
00597 dbus_bool_t v;
00598
00599 _dbus_return_val_if_fail (connection != NULL, FALSE);
00600
00601 CONNECTION_LOCK (connection);
00602 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00603 CONNECTION_UNLOCK (connection);
00604
00605 return v;
00606 }
00607
00615 DBusMessage*
00616 _dbus_connection_get_message_to_send (DBusConnection *connection)
00617 {
00618 HAVE_LOCK_CHECK (connection);
00619
00620 return _dbus_list_get_last (&connection->outgoing_messages);
00621 }
00622
00631 void
00632 _dbus_connection_message_sent_unlocked (DBusConnection *connection,
00633 DBusMessage *message)
00634 {
00635 DBusList *link;
00636
00637 HAVE_LOCK_CHECK (connection);
00638
00639
00640
00641
00642
00643
00644 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00645 _dbus_assert (link != NULL);
00646 _dbus_assert (link->data == message);
00647
00648 _dbus_list_unlink (&connection->outgoing_messages,
00649 link);
00650 _dbus_list_prepend_link (&connection->expired_messages, link);
00651
00652 connection->n_outgoing -= 1;
00653
00654 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00655 message,
00656 dbus_message_type_to_string (dbus_message_get_type (message)),
00657 dbus_message_get_path (message) ?
00658 dbus_message_get_path (message) :
00659 "no path",
00660 dbus_message_get_interface (message) ?
00661 dbus_message_get_interface (message) :
00662 "no interface",
00663 dbus_message_get_member (message) ?
00664 dbus_message_get_member (message) :
00665 "no member",
00666 dbus_message_get_signature (message),
00667 connection, connection->n_outgoing);
00668
00669
00670
00671 _dbus_message_remove_counter (message, connection->outgoing_counter);
00672
00673
00674 }
00675
00677 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00678 DBusWatch *watch);
00680 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00681 DBusWatch *watch);
00683 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00684 DBusWatch *watch,
00685 dbus_bool_t enabled);
00686
00687 static dbus_bool_t
00688 protected_change_watch (DBusConnection *connection,
00689 DBusWatch *watch,
00690 DBusWatchAddFunction add_function,
00691 DBusWatchRemoveFunction remove_function,
00692 DBusWatchToggleFunction toggle_function,
00693 dbus_bool_t enabled)
00694 {
00695 dbus_bool_t retval;
00696
00697 HAVE_LOCK_CHECK (connection);
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 if (connection->watches)
00718 {
00719 if (add_function)
00720 retval = (* add_function) (connection->watches, watch);
00721 else if (remove_function)
00722 {
00723 retval = TRUE;
00724 (* remove_function) (connection->watches, watch);
00725 }
00726 else
00727 {
00728 retval = TRUE;
00729 (* toggle_function) (connection->watches, watch, enabled);
00730 }
00731 return retval;
00732 }
00733 else
00734 return FALSE;
00735 }
00736
00737
00749 dbus_bool_t
00750 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00751 DBusWatch *watch)
00752 {
00753 return protected_change_watch (connection, watch,
00754 _dbus_watch_list_add_watch,
00755 NULL, NULL, FALSE);
00756 }
00757
00767 void
00768 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00769 DBusWatch *watch)
00770 {
00771 protected_change_watch (connection, watch,
00772 NULL,
00773 _dbus_watch_list_remove_watch,
00774 NULL, FALSE);
00775 }
00776
00787 void
00788 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00789 DBusWatch *watch,
00790 dbus_bool_t enabled)
00791 {
00792 _dbus_assert (watch != NULL);
00793
00794 protected_change_watch (connection, watch,
00795 NULL, NULL,
00796 _dbus_watch_list_toggle_watch,
00797 enabled);
00798 }
00799
00801 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00802 DBusTimeout *timeout);
00804 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00805 DBusTimeout *timeout);
00807 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00808 DBusTimeout *timeout,
00809 dbus_bool_t enabled);
00810
00811 static dbus_bool_t
00812 protected_change_timeout (DBusConnection *connection,
00813 DBusTimeout *timeout,
00814 DBusTimeoutAddFunction add_function,
00815 DBusTimeoutRemoveFunction remove_function,
00816 DBusTimeoutToggleFunction toggle_function,
00817 dbus_bool_t enabled)
00818 {
00819 dbus_bool_t retval;
00820
00821 HAVE_LOCK_CHECK (connection);
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 if (connection->timeouts)
00842 {
00843 if (add_function)
00844 retval = (* add_function) (connection->timeouts, timeout);
00845 else if (remove_function)
00846 {
00847 retval = TRUE;
00848 (* remove_function) (connection->timeouts, timeout);
00849 }
00850 else
00851 {
00852 retval = TRUE;
00853 (* toggle_function) (connection->timeouts, timeout, enabled);
00854 }
00855 return retval;
00856 }
00857 else
00858 return FALSE;
00859 }
00860
00873 dbus_bool_t
00874 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00875 DBusTimeout *timeout)
00876 {
00877 return protected_change_timeout (connection, timeout,
00878 _dbus_timeout_list_add_timeout,
00879 NULL, NULL, FALSE);
00880 }
00881
00891 void
00892 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00893 DBusTimeout *timeout)
00894 {
00895 protected_change_timeout (connection, timeout,
00896 NULL,
00897 _dbus_timeout_list_remove_timeout,
00898 NULL, FALSE);
00899 }
00900
00911 void
00912 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00913 DBusTimeout *timeout,
00914 dbus_bool_t enabled)
00915 {
00916 protected_change_timeout (connection, timeout,
00917 NULL, NULL,
00918 _dbus_timeout_list_toggle_timeout,
00919 enabled);
00920 }
00921
00922 static dbus_bool_t
00923 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00924 DBusPendingCall *pending)
00925 {
00926 dbus_uint32_t reply_serial;
00927 DBusTimeout *timeout;
00928
00929 HAVE_LOCK_CHECK (connection);
00930
00931 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00932
00933 _dbus_assert (reply_serial != 0);
00934
00935 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00936
00937 if (timeout)
00938 {
00939 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00940 return FALSE;
00941
00942 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00943 reply_serial,
00944 pending))
00945 {
00946 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00947
00948 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00949 HAVE_LOCK_CHECK (connection);
00950 return FALSE;
00951 }
00952
00953 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00954 }
00955 else
00956 {
00957 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00958 reply_serial,
00959 pending))
00960 {
00961 HAVE_LOCK_CHECK (connection);
00962 return FALSE;
00963 }
00964 }
00965
00966 _dbus_pending_call_ref_unlocked (pending);
00967
00968 HAVE_LOCK_CHECK (connection);
00969
00970 return TRUE;
00971 }
00972
00973 static void
00974 free_pending_call_on_hash_removal (void *data)
00975 {
00976 DBusPendingCall *pending;
00977 DBusConnection *connection;
00978
00979 if (data == NULL)
00980 return;
00981
00982 pending = data;
00983
00984 connection = _dbus_pending_call_get_connection_unlocked (pending);
00985
00986 HAVE_LOCK_CHECK (connection);
00987
00988 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00989 {
00990 _dbus_connection_remove_timeout_unlocked (connection,
00991 _dbus_pending_call_get_timeout_unlocked (pending));
00992
00993 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00994 }
00995
00996
00997
00998
00999
01000
01001 _dbus_connection_ref_unlocked (connection);
01002 _dbus_pending_call_unref_and_unlock (pending);
01003 CONNECTION_LOCK (connection);
01004 _dbus_connection_unref_unlocked (connection);
01005 }
01006
01007 static void
01008 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
01009 DBusPendingCall *pending)
01010 {
01011
01012
01013
01014 _dbus_hash_table_remove_int (connection->pending_replies,
01015 _dbus_pending_call_get_reply_serial_unlocked (pending));
01016 }
01017
01018 static void
01019 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
01020 DBusPendingCall *pending)
01021 {
01022
01023
01024
01025
01026
01027
01028
01029 _dbus_pending_call_ref_unlocked (pending);
01030 _dbus_hash_table_remove_int (connection->pending_replies,
01031 _dbus_pending_call_get_reply_serial_unlocked (pending));
01032
01033 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01034 _dbus_connection_remove_timeout_unlocked (connection,
01035 _dbus_pending_call_get_timeout_unlocked (pending));
01036
01037 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01038
01039 _dbus_pending_call_unref_and_unlock (pending);
01040 }
01041
01050 void
01051 _dbus_connection_remove_pending_call (DBusConnection *connection,
01052 DBusPendingCall *pending)
01053 {
01054 CONNECTION_LOCK (connection);
01055 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01056 }
01057
01067 static dbus_bool_t
01068 _dbus_connection_acquire_io_path (DBusConnection *connection,
01069 int timeout_milliseconds)
01070 {
01071 dbus_bool_t we_acquired;
01072
01073 HAVE_LOCK_CHECK (connection);
01074
01075
01076 _dbus_connection_ref_unlocked (connection);
01077
01078
01079 CONNECTION_UNLOCK (connection);
01080
01081 _dbus_verbose ("locking io_path_mutex\n");
01082 _dbus_cmutex_lock (connection->io_path_mutex);
01083
01084 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01085 connection->io_path_acquired, timeout_milliseconds);
01086
01087 we_acquired = FALSE;
01088
01089 if (connection->io_path_acquired)
01090 {
01091 if (timeout_milliseconds != -1)
01092 {
01093 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01094 timeout_milliseconds);
01095
01096 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01097 connection->io_path_mutex,
01098 timeout_milliseconds))
01099 {
01100
01101
01102
01103
01104
01105
01106
01107
01108 }
01109 }
01110 else
01111 {
01112 while (connection->io_path_acquired)
01113 {
01114 _dbus_verbose ("waiting for IO path to be acquirable\n");
01115 _dbus_condvar_wait (connection->io_path_cond,
01116 connection->io_path_mutex);
01117 }
01118 }
01119 }
01120
01121 if (!connection->io_path_acquired)
01122 {
01123 we_acquired = TRUE;
01124 connection->io_path_acquired = TRUE;
01125 }
01126
01127 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01128 connection->io_path_acquired, we_acquired);
01129
01130 _dbus_verbose ("unlocking io_path_mutex\n");
01131 _dbus_cmutex_unlock (connection->io_path_mutex);
01132
01133 CONNECTION_LOCK (connection);
01134
01135 HAVE_LOCK_CHECK (connection);
01136
01137 _dbus_connection_unref_unlocked (connection);
01138
01139 return we_acquired;
01140 }
01141
01149 static void
01150 _dbus_connection_release_io_path (DBusConnection *connection)
01151 {
01152 HAVE_LOCK_CHECK (connection);
01153
01154 _dbus_verbose ("locking io_path_mutex\n");
01155 _dbus_cmutex_lock (connection->io_path_mutex);
01156
01157 _dbus_assert (connection->io_path_acquired);
01158
01159 _dbus_verbose ("start connection->io_path_acquired = %d\n",
01160 connection->io_path_acquired);
01161
01162 connection->io_path_acquired = FALSE;
01163 _dbus_condvar_wake_one (connection->io_path_cond);
01164
01165 _dbus_verbose ("unlocking io_path_mutex\n");
01166 _dbus_cmutex_unlock (connection->io_path_mutex);
01167 }
01168
01204 void
01205 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01206 DBusPendingCall *pending,
01207 unsigned int flags,
01208 int timeout_milliseconds)
01209 {
01210 _dbus_verbose ("start\n");
01211
01212 HAVE_LOCK_CHECK (connection);
01213
01214 if (connection->n_outgoing == 0)
01215 flags &= ~DBUS_ITERATION_DO_WRITING;
01216
01217 if (_dbus_connection_acquire_io_path (connection,
01218 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01219 {
01220 HAVE_LOCK_CHECK (connection);
01221
01222 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01223 {
01224 _dbus_verbose ("pending call completed while acquiring I/O path");
01225 }
01226 else if ( (pending != NULL) &&
01227 _dbus_connection_peek_for_reply_unlocked (connection,
01228 _dbus_pending_call_get_reply_serial_unlocked (pending)))
01229 {
01230 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01231 }
01232 else
01233 {
01234 _dbus_transport_do_iteration (connection->transport,
01235 flags, timeout_milliseconds);
01236 }
01237
01238 _dbus_connection_release_io_path (connection);
01239 }
01240
01241 HAVE_LOCK_CHECK (connection);
01242
01243 _dbus_verbose ("end\n");
01244 }
01245
01255 DBusConnection*
01256 _dbus_connection_new_for_transport (DBusTransport *transport)
01257 {
01258 DBusConnection *connection;
01259 DBusWatchList *watch_list;
01260 DBusTimeoutList *timeout_list;
01261 DBusHashTable *pending_replies;
01262 DBusList *disconnect_link;
01263 DBusMessage *disconnect_message;
01264 DBusCounter *outgoing_counter;
01265 DBusObjectTree *objects;
01266
01267 watch_list = NULL;
01268 connection = NULL;
01269 pending_replies = NULL;
01270 timeout_list = NULL;
01271 disconnect_link = NULL;
01272 disconnect_message = NULL;
01273 outgoing_counter = NULL;
01274 objects = NULL;
01275
01276 watch_list = _dbus_watch_list_new ();
01277 if (watch_list == NULL)
01278 goto error;
01279
01280 timeout_list = _dbus_timeout_list_new ();
01281 if (timeout_list == NULL)
01282 goto error;
01283
01284 pending_replies =
01285 _dbus_hash_table_new (DBUS_HASH_INT,
01286 NULL,
01287 (DBusFreeFunction)free_pending_call_on_hash_removal);
01288 if (pending_replies == NULL)
01289 goto error;
01290
01291 connection = dbus_new0 (DBusConnection, 1);
01292 if (connection == NULL)
01293 goto error;
01294
01295 _dbus_rmutex_new_at_location (&connection->mutex);
01296 if (connection->mutex == NULL)
01297 goto error;
01298
01299 _dbus_cmutex_new_at_location (&connection->io_path_mutex);
01300 if (connection->io_path_mutex == NULL)
01301 goto error;
01302
01303 _dbus_cmutex_new_at_location (&connection->dispatch_mutex);
01304 if (connection->dispatch_mutex == NULL)
01305 goto error;
01306
01307 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01308 if (connection->dispatch_cond == NULL)
01309 goto error;
01310
01311 _dbus_condvar_new_at_location (&connection->io_path_cond);
01312 if (connection->io_path_cond == NULL)
01313 goto error;
01314
01315 _dbus_rmutex_new_at_location (&connection->slot_mutex);
01316 if (connection->slot_mutex == NULL)
01317 goto error;
01318
01319 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01320 DBUS_INTERFACE_LOCAL,
01321 "Disconnected");
01322
01323 if (disconnect_message == NULL)
01324 goto error;
01325
01326 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01327 if (disconnect_link == NULL)
01328 goto error;
01329
01330 outgoing_counter = _dbus_counter_new ();
01331 if (outgoing_counter == NULL)
01332 goto error;
01333
01334 objects = _dbus_object_tree_new (connection);
01335 if (objects == NULL)
01336 goto error;
01337
01338 if (_dbus_modify_sigpipe)
01339 _dbus_disable_sigpipe ();
01340
01341
01342 _dbus_atomic_inc (&connection->refcount);
01343 connection->transport = transport;
01344 connection->watches = watch_list;
01345 connection->timeouts = timeout_list;
01346 connection->pending_replies = pending_replies;
01347 connection->outgoing_counter = outgoing_counter;
01348 connection->filter_list = NULL;
01349 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01350 connection->objects = objects;
01351 connection->exit_on_disconnect = FALSE;
01352 connection->shareable = FALSE;
01353 connection->route_peer_messages = FALSE;
01354 connection->disconnected_message_arrived = FALSE;
01355 connection->disconnected_message_processed = FALSE;
01356
01357 #ifndef DBUS_DISABLE_CHECKS
01358 connection->generation = _dbus_current_generation;
01359 #endif
01360
01361 _dbus_data_slot_list_init (&connection->slot_list);
01362
01363 connection->client_serial = 1;
01364
01365 connection->disconnect_message_link = disconnect_link;
01366
01367 CONNECTION_LOCK (connection);
01368
01369 if (!_dbus_transport_set_connection (transport, connection))
01370 {
01371 CONNECTION_UNLOCK (connection);
01372
01373 goto error;
01374 }
01375
01376 _dbus_transport_ref (transport);
01377
01378 CONNECTION_UNLOCK (connection);
01379
01380 _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
01381 return connection;
01382
01383 error:
01384 if (disconnect_message != NULL)
01385 dbus_message_unref (disconnect_message);
01386
01387 if (disconnect_link != NULL)
01388 _dbus_list_free_link (disconnect_link);
01389
01390 if (connection != NULL)
01391 {
01392 _dbus_condvar_free_at_location (&connection->io_path_cond);
01393 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01394 _dbus_rmutex_free_at_location (&connection->mutex);
01395 _dbus_cmutex_free_at_location (&connection->io_path_mutex);
01396 _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
01397 _dbus_rmutex_free_at_location (&connection->slot_mutex);
01398 dbus_free (connection);
01399 }
01400 if (pending_replies)
01401 _dbus_hash_table_unref (pending_replies);
01402
01403 if (watch_list)
01404 _dbus_watch_list_free (watch_list);
01405
01406 if (timeout_list)
01407 _dbus_timeout_list_free (timeout_list);
01408
01409 if (outgoing_counter)
01410 _dbus_counter_unref (outgoing_counter);
01411
01412 if (objects)
01413 _dbus_object_tree_unref (objects);
01414
01415 return NULL;
01416 }
01417
01425 DBusConnection *
01426 _dbus_connection_ref_unlocked (DBusConnection *connection)
01427 {
01428 dbus_int32_t old_refcount;
01429
01430 _dbus_assert (connection != NULL);
01431 _dbus_assert (connection->generation == _dbus_current_generation);
01432
01433 HAVE_LOCK_CHECK (connection);
01434
01435 old_refcount = _dbus_atomic_inc (&connection->refcount);
01436 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
01437 "ref_unlocked");
01438
01439 return connection;
01440 }
01441
01448 void
01449 _dbus_connection_unref_unlocked (DBusConnection *connection)
01450 {
01451 dbus_int32_t old_refcount;
01452
01453 HAVE_LOCK_CHECK (connection);
01454
01455 _dbus_assert (connection != NULL);
01456
01457 old_refcount = _dbus_atomic_dec (&connection->refcount);
01458
01459 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
01460 "unref_unlocked");
01461
01462 if (old_refcount == 1)
01463 _dbus_connection_last_unref (connection);
01464 }
01465
01466 static dbus_uint32_t
01467 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01468 {
01469 dbus_uint32_t serial;
01470
01471 serial = connection->client_serial++;
01472
01473 if (connection->client_serial == 0)
01474 connection->client_serial = 1;
01475
01476 return serial;
01477 }
01478
01492 dbus_bool_t
01493 _dbus_connection_handle_watch (DBusWatch *watch,
01494 unsigned int condition,
01495 void *data)
01496 {
01497 DBusConnection *connection;
01498 dbus_bool_t retval;
01499 DBusDispatchStatus status;
01500
01501 connection = data;
01502
01503 _dbus_verbose ("start\n");
01504
01505 CONNECTION_LOCK (connection);
01506
01507 if (!_dbus_connection_acquire_io_path (connection, 1))
01508 {
01509
01510 CONNECTION_UNLOCK (connection);
01511 return TRUE;
01512 }
01513
01514 HAVE_LOCK_CHECK (connection);
01515 retval = _dbus_transport_handle_watch (connection->transport,
01516 watch, condition);
01517
01518 _dbus_connection_release_io_path (connection);
01519
01520 HAVE_LOCK_CHECK (connection);
01521
01522 _dbus_verbose ("middle\n");
01523
01524 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01525
01526
01527 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01528
01529 _dbus_verbose ("end\n");
01530
01531 return retval;
01532 }
01533
01534 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01535 static DBusHashTable *shared_connections = NULL;
01536 static DBusList *shared_connections_no_guid = NULL;
01537
01538 static void
01539 close_connection_on_shutdown (DBusConnection *connection)
01540 {
01541 DBusMessage *message;
01542
01543 dbus_connection_ref (connection);
01544 _dbus_connection_close_possibly_shared (connection);
01545
01546
01547 while ((message = dbus_connection_pop_message (connection)))
01548 {
01549 dbus_message_unref (message);
01550 }
01551 dbus_connection_unref (connection);
01552 }
01553
01554 static void
01555 shared_connections_shutdown (void *data)
01556 {
01557 int n_entries;
01558
01559 _DBUS_LOCK (shared_connections);
01560
01561
01562 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01563 {
01564 DBusConnection *connection;
01565 DBusHashIter iter;
01566
01567 _dbus_hash_iter_init (shared_connections, &iter);
01568 _dbus_hash_iter_next (&iter);
01569
01570 connection = _dbus_hash_iter_get_value (&iter);
01571
01572 _DBUS_UNLOCK (shared_connections);
01573 close_connection_on_shutdown (connection);
01574 _DBUS_LOCK (shared_connections);
01575
01576
01577 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01578 }
01579
01580 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01581
01582 _dbus_hash_table_unref (shared_connections);
01583 shared_connections = NULL;
01584
01585 if (shared_connections_no_guid != NULL)
01586 {
01587 DBusConnection *connection;
01588 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01589 while (connection != NULL)
01590 {
01591 _DBUS_UNLOCK (shared_connections);
01592 close_connection_on_shutdown (connection);
01593 _DBUS_LOCK (shared_connections);
01594 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01595 }
01596 }
01597
01598 shared_connections_no_guid = NULL;
01599
01600 _DBUS_UNLOCK (shared_connections);
01601 }
01602
01603 static dbus_bool_t
01604 connection_lookup_shared (DBusAddressEntry *entry,
01605 DBusConnection **result)
01606 {
01607 _dbus_verbose ("checking for existing connection\n");
01608
01609 *result = NULL;
01610
01611 _DBUS_LOCK (shared_connections);
01612
01613 if (shared_connections == NULL)
01614 {
01615 _dbus_verbose ("creating shared_connections hash table\n");
01616
01617 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01618 dbus_free,
01619 NULL);
01620 if (shared_connections == NULL)
01621 {
01622 _DBUS_UNLOCK (shared_connections);
01623 return FALSE;
01624 }
01625
01626 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01627 {
01628 _dbus_hash_table_unref (shared_connections);
01629 shared_connections = NULL;
01630 _DBUS_UNLOCK (shared_connections);
01631 return FALSE;
01632 }
01633
01634 _dbus_verbose (" successfully created shared_connections\n");
01635
01636 _DBUS_UNLOCK (shared_connections);
01637 return TRUE;
01638 }
01639 else
01640 {
01641 const char *guid;
01642
01643 guid = dbus_address_entry_get_value (entry, "guid");
01644
01645 if (guid != NULL)
01646 {
01647 DBusConnection *connection;
01648
01649 connection = _dbus_hash_table_lookup_string (shared_connections,
01650 guid);
01651
01652 if (connection)
01653 {
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 CONNECTION_LOCK (connection);
01669 if (_dbus_connection_get_is_connected_unlocked (connection))
01670 {
01671 _dbus_connection_ref_unlocked (connection);
01672 *result = connection;
01673 _dbus_verbose ("looked up existing connection to server guid %s\n",
01674 guid);
01675 }
01676 else
01677 {
01678 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01679 guid);
01680 }
01681 CONNECTION_UNLOCK (connection);
01682 }
01683 }
01684
01685 _DBUS_UNLOCK (shared_connections);
01686 return TRUE;
01687 }
01688 }
01689
01690 static dbus_bool_t
01691 connection_record_shared_unlocked (DBusConnection *connection,
01692 const char *guid)
01693 {
01694 char *guid_key;
01695 char *guid_in_connection;
01696
01697 HAVE_LOCK_CHECK (connection);
01698 _dbus_assert (connection->server_guid == NULL);
01699 _dbus_assert (connection->shareable);
01700
01701
01702
01703
01704
01705 _dbus_connection_ref_unlocked (connection);
01706
01707 if (guid == NULL)
01708 {
01709 _DBUS_LOCK (shared_connections);
01710
01711 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01712 {
01713 _DBUS_UNLOCK (shared_connections);
01714 return FALSE;
01715 }
01716
01717 _DBUS_UNLOCK (shared_connections);
01718 return TRUE;
01719 }
01720
01721
01722
01723
01724
01725
01726 guid_key = _dbus_strdup (guid);
01727 if (guid_key == NULL)
01728 return FALSE;
01729
01730 guid_in_connection = _dbus_strdup (guid);
01731 if (guid_in_connection == NULL)
01732 {
01733 dbus_free (guid_key);
01734 return FALSE;
01735 }
01736
01737 _DBUS_LOCK (shared_connections);
01738 _dbus_assert (shared_connections != NULL);
01739
01740 if (!_dbus_hash_table_insert_string (shared_connections,
01741 guid_key, connection))
01742 {
01743 dbus_free (guid_key);
01744 dbus_free (guid_in_connection);
01745 _DBUS_UNLOCK (shared_connections);
01746 return FALSE;
01747 }
01748
01749 connection->server_guid = guid_in_connection;
01750
01751 _dbus_verbose ("stored connection to %s to be shared\n",
01752 connection->server_guid);
01753
01754 _DBUS_UNLOCK (shared_connections);
01755
01756 _dbus_assert (connection->server_guid != NULL);
01757
01758 return TRUE;
01759 }
01760
01761 static void
01762 connection_forget_shared_unlocked (DBusConnection *connection)
01763 {
01764 HAVE_LOCK_CHECK (connection);
01765
01766 if (!connection->shareable)
01767 return;
01768
01769 _DBUS_LOCK (shared_connections);
01770
01771 if (connection->server_guid != NULL)
01772 {
01773 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01774 connection->server_guid);
01775
01776 if (!_dbus_hash_table_remove_string (shared_connections,
01777 connection->server_guid))
01778 _dbus_assert_not_reached ("connection was not in the shared table");
01779
01780 dbus_free (connection->server_guid);
01781 connection->server_guid = NULL;
01782 }
01783 else
01784 {
01785 _dbus_list_remove (&shared_connections_no_guid, connection);
01786 }
01787
01788 _DBUS_UNLOCK (shared_connections);
01789
01790
01791 _dbus_connection_unref_unlocked (connection);
01792 }
01793
01794 static DBusConnection*
01795 connection_try_from_address_entry (DBusAddressEntry *entry,
01796 DBusError *error)
01797 {
01798 DBusTransport *transport;
01799 DBusConnection *connection;
01800
01801 transport = _dbus_transport_open (entry, error);
01802
01803 if (transport == NULL)
01804 {
01805 _DBUS_ASSERT_ERROR_IS_SET (error);
01806 return NULL;
01807 }
01808
01809 connection = _dbus_connection_new_for_transport (transport);
01810
01811 _dbus_transport_unref (transport);
01812
01813 if (connection == NULL)
01814 {
01815 _DBUS_SET_OOM (error);
01816 return NULL;
01817 }
01818
01819 #ifndef DBUS_DISABLE_CHECKS
01820 _dbus_assert (!connection->have_connection_lock);
01821 #endif
01822 return connection;
01823 }
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 static DBusConnection*
01838 _dbus_connection_open_internal (const char *address,
01839 dbus_bool_t shared,
01840 DBusError *error)
01841 {
01842 DBusConnection *connection;
01843 DBusAddressEntry **entries;
01844 DBusError tmp_error = DBUS_ERROR_INIT;
01845 DBusError first_error = DBUS_ERROR_INIT;
01846 int len, i;
01847
01848 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01849
01850 _dbus_verbose ("opening %s connection to: %s\n",
01851 shared ? "shared" : "private", address);
01852
01853 if (!dbus_parse_address (address, &entries, &len, error))
01854 return NULL;
01855
01856 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01857
01858 connection = NULL;
01859
01860 for (i = 0; i < len; i++)
01861 {
01862 if (shared)
01863 {
01864 if (!connection_lookup_shared (entries[i], &connection))
01865 _DBUS_SET_OOM (&tmp_error);
01866 }
01867
01868 if (connection == NULL)
01869 {
01870 connection = connection_try_from_address_entry (entries[i],
01871 &tmp_error);
01872
01873 if (connection != NULL && shared)
01874 {
01875 const char *guid;
01876
01877 connection->shareable = TRUE;
01878
01879
01880 guid = dbus_address_entry_get_value (entries[i], "guid");
01881
01882 CONNECTION_LOCK (connection);
01883
01884 if (!connection_record_shared_unlocked (connection, guid))
01885 {
01886 _DBUS_SET_OOM (&tmp_error);
01887 _dbus_connection_close_possibly_shared_and_unlock (connection);
01888 dbus_connection_unref (connection);
01889 connection = NULL;
01890 }
01891 else
01892 CONNECTION_UNLOCK (connection);
01893 }
01894 }
01895
01896 if (connection)
01897 break;
01898
01899 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01900
01901 if (i == 0)
01902 dbus_move_error (&tmp_error, &first_error);
01903 else
01904 dbus_error_free (&tmp_error);
01905 }
01906
01907 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01908 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01909
01910 if (connection == NULL)
01911 {
01912 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01913 dbus_move_error (&first_error, error);
01914 }
01915 else
01916 dbus_error_free (&first_error);
01917
01918 dbus_address_entries_free (entries);
01919 return connection;
01920 }
01921
01930 void
01931 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01932 {
01933 _dbus_assert (connection != NULL);
01934 _dbus_assert (connection->generation == _dbus_current_generation);
01935
01936 CONNECTION_LOCK (connection);
01937 _dbus_connection_close_possibly_shared_and_unlock (connection);
01938 }
01939
01940 static DBusPreallocatedSend*
01941 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01942 {
01943 DBusPreallocatedSend *preallocated;
01944
01945 HAVE_LOCK_CHECK (connection);
01946
01947 _dbus_assert (connection != NULL);
01948
01949 preallocated = dbus_new (DBusPreallocatedSend, 1);
01950 if (preallocated == NULL)
01951 return NULL;
01952
01953 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01954 if (preallocated->queue_link == NULL)
01955 goto failed_0;
01956
01957 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01958 if (preallocated->counter_link == NULL)
01959 goto failed_1;
01960
01961 _dbus_counter_ref (preallocated->counter_link->data);
01962
01963 preallocated->connection = connection;
01964
01965 return preallocated;
01966
01967 failed_1:
01968 _dbus_list_free_link (preallocated->queue_link);
01969 failed_0:
01970 dbus_free (preallocated);
01971
01972 return NULL;
01973 }
01974
01975
01976 static void
01977 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01978 DBusPreallocatedSend *preallocated,
01979 DBusMessage *message,
01980 dbus_uint32_t *client_serial)
01981 {
01982 dbus_uint32_t serial;
01983
01984 preallocated->queue_link->data = message;
01985 _dbus_list_prepend_link (&connection->outgoing_messages,
01986 preallocated->queue_link);
01987
01988
01989
01990 _dbus_message_add_counter_link (message,
01991 preallocated->counter_link);
01992
01993 dbus_free (preallocated);
01994 preallocated = NULL;
01995
01996 dbus_message_ref (message);
01997
01998 connection->n_outgoing += 1;
01999
02000 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02001 message,
02002 dbus_message_type_to_string (dbus_message_get_type (message)),
02003 dbus_message_get_path (message) ?
02004 dbus_message_get_path (message) :
02005 "no path",
02006 dbus_message_get_interface (message) ?
02007 dbus_message_get_interface (message) :
02008 "no interface",
02009 dbus_message_get_member (message) ?
02010 dbus_message_get_member (message) :
02011 "no member",
02012 dbus_message_get_signature (message),
02013 dbus_message_get_destination (message) ?
02014 dbus_message_get_destination (message) :
02015 "null",
02016 connection,
02017 connection->n_outgoing);
02018
02019 if (dbus_message_get_serial (message) == 0)
02020 {
02021 serial = _dbus_connection_get_next_client_serial (connection);
02022 dbus_message_set_serial (message, serial);
02023 if (client_serial)
02024 *client_serial = serial;
02025 }
02026 else
02027 {
02028 if (client_serial)
02029 *client_serial = dbus_message_get_serial (message);
02030 }
02031
02032 _dbus_verbose ("Message %p serial is %u\n",
02033 message, dbus_message_get_serial (message));
02034
02035 dbus_message_lock (message);
02036
02037
02038
02039
02040 _dbus_connection_do_iteration_unlocked (connection,
02041 NULL,
02042 DBUS_ITERATION_DO_WRITING,
02043 -1);
02044
02045
02046 if (connection->n_outgoing > 0)
02047 _dbus_connection_wakeup_mainloop (connection);
02048 }
02049
02050 static void
02051 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02052 DBusPreallocatedSend *preallocated,
02053 DBusMessage *message,
02054 dbus_uint32_t *client_serial)
02055 {
02056 DBusDispatchStatus status;
02057
02058 HAVE_LOCK_CHECK (connection);
02059
02060 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02061 preallocated,
02062 message, client_serial);
02063
02064 _dbus_verbose ("middle\n");
02065 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02066
02067
02068 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02069 }
02070
02080 dbus_bool_t
02081 _dbus_connection_send_and_unlock (DBusConnection *connection,
02082 DBusMessage *message,
02083 dbus_uint32_t *client_serial)
02084 {
02085 DBusPreallocatedSend *preallocated;
02086
02087 _dbus_assert (connection != NULL);
02088 _dbus_assert (message != NULL);
02089
02090 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02091 if (preallocated == NULL)
02092 {
02093 CONNECTION_UNLOCK (connection);
02094 return FALSE;
02095 }
02096
02097 _dbus_connection_send_preallocated_and_unlock (connection,
02098 preallocated,
02099 message,
02100 client_serial);
02101 return TRUE;
02102 }
02103
02128 void
02129 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02130 {
02131 dbus_int32_t refcount;
02132
02133 CONNECTION_LOCK (connection);
02134
02135 refcount = _dbus_atomic_get (&connection->refcount);
02136
02137 _dbus_assert (refcount >= 1);
02138
02139 if (refcount == 1)
02140 _dbus_connection_close_possibly_shared_and_unlock (connection);
02141 else
02142 CONNECTION_UNLOCK (connection);
02143 }
02144
02145
02155 static void
02156 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02157 {
02158 if (timeout_milliseconds == -1)
02159 _dbus_sleep_milliseconds (1000);
02160 else if (timeout_milliseconds < 100)
02161 ;
02162 else if (timeout_milliseconds <= 1000)
02163 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02164 else
02165 _dbus_sleep_milliseconds (1000);
02166 }
02167
02168 static DBusMessage *
02169 generate_local_error_message (dbus_uint32_t serial,
02170 char *error_name,
02171 char *error_msg)
02172 {
02173 DBusMessage *message;
02174 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02175 if (!message)
02176 goto out;
02177
02178 if (!dbus_message_set_error_name (message, error_name))
02179 {
02180 dbus_message_unref (message);
02181 message = NULL;
02182 goto out;
02183 }
02184
02185 dbus_message_set_no_reply (message, TRUE);
02186
02187 if (!dbus_message_set_reply_serial (message,
02188 serial))
02189 {
02190 dbus_message_unref (message);
02191 message = NULL;
02192 goto out;
02193 }
02194
02195 if (error_msg != NULL)
02196 {
02197 DBusMessageIter iter;
02198
02199 dbus_message_iter_init_append (message, &iter);
02200 if (!dbus_message_iter_append_basic (&iter,
02201 DBUS_TYPE_STRING,
02202 &error_msg))
02203 {
02204 dbus_message_unref (message);
02205 message = NULL;
02206 goto out;
02207 }
02208 }
02209
02210 out:
02211 return message;
02212 }
02213
02214
02215
02216
02217 static dbus_bool_t
02218 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02219 dbus_uint32_t client_serial)
02220 {
02221 DBusList *link;
02222 HAVE_LOCK_CHECK (connection);
02223
02224 link = _dbus_list_get_first_link (&connection->incoming_messages);
02225
02226 while (link != NULL)
02227 {
02228 DBusMessage *reply = link->data;
02229
02230 if (dbus_message_get_reply_serial (reply) == client_serial)
02231 {
02232 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02233 return TRUE;
02234 }
02235 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02236 }
02237
02238 return FALSE;
02239 }
02240
02241
02242
02243
02244 static DBusMessage*
02245 check_for_reply_unlocked (DBusConnection *connection,
02246 dbus_uint32_t client_serial)
02247 {
02248 DBusList *link;
02249
02250 HAVE_LOCK_CHECK (connection);
02251
02252 link = _dbus_list_get_first_link (&connection->incoming_messages);
02253
02254 while (link != NULL)
02255 {
02256 DBusMessage *reply = link->data;
02257
02258 if (dbus_message_get_reply_serial (reply) == client_serial)
02259 {
02260 _dbus_list_remove_link (&connection->incoming_messages, link);
02261 connection->n_incoming -= 1;
02262 return reply;
02263 }
02264 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02265 }
02266
02267 return NULL;
02268 }
02269
02270 static void
02271 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02272 {
02273
02274
02275
02276
02277
02278 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02279 {
02280 DBusPendingCall *pending;
02281 DBusHashIter iter;
02282
02283 _dbus_hash_iter_init (connection->pending_replies, &iter);
02284 _dbus_hash_iter_next (&iter);
02285
02286 pending = _dbus_hash_iter_get_value (&iter);
02287 _dbus_pending_call_ref_unlocked (pending);
02288
02289 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02290 connection);
02291
02292 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02293 _dbus_connection_remove_timeout_unlocked (connection,
02294 _dbus_pending_call_get_timeout_unlocked (pending));
02295 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02296 _dbus_hash_iter_remove_entry (&iter);
02297
02298 _dbus_pending_call_unref_and_unlock (pending);
02299 CONNECTION_LOCK (connection);
02300 }
02301 HAVE_LOCK_CHECK (connection);
02302 }
02303
02304 static void
02305 complete_pending_call_and_unlock (DBusConnection *connection,
02306 DBusPendingCall *pending,
02307 DBusMessage *message)
02308 {
02309 _dbus_pending_call_set_reply_unlocked (pending, message);
02310 _dbus_pending_call_ref_unlocked (pending);
02311 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02312
02313
02314 _dbus_pending_call_complete (pending);
02315 dbus_pending_call_unref (pending);
02316 }
02317
02318 static dbus_bool_t
02319 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02320 DBusPendingCall *pending)
02321 {
02322 DBusMessage *reply;
02323 DBusDispatchStatus status;
02324
02325 reply = check_for_reply_unlocked (connection,
02326 _dbus_pending_call_get_reply_serial_unlocked (pending));
02327 if (reply != NULL)
02328 {
02329 _dbus_verbose ("checked for reply\n");
02330
02331 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02332
02333 complete_pending_call_and_unlock (connection, pending, reply);
02334 dbus_message_unref (reply);
02335
02336 CONNECTION_LOCK (connection);
02337 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02338 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02339 dbus_pending_call_unref (pending);
02340
02341 return TRUE;
02342 }
02343
02344 return FALSE;
02345 }
02346
02361 void
02362 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02363 {
02364 long start_tv_sec, start_tv_usec;
02365 long tv_sec, tv_usec;
02366 DBusDispatchStatus status;
02367 DBusConnection *connection;
02368 dbus_uint32_t client_serial;
02369 DBusTimeout *timeout;
02370 int timeout_milliseconds, elapsed_milliseconds;
02371
02372 _dbus_assert (pending != NULL);
02373
02374 if (dbus_pending_call_get_completed (pending))
02375 return;
02376
02377 dbus_pending_call_ref (pending);
02378
02379 connection = _dbus_pending_call_get_connection_and_lock (pending);
02380
02381
02382 _dbus_connection_flush_unlocked (connection);
02383
02384 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02385
02386
02387
02388
02389
02390 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02391 _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
02392 if (timeout)
02393 {
02394 timeout_milliseconds = dbus_timeout_get_interval (timeout);
02395
02396 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02397 timeout_milliseconds,
02398 client_serial,
02399 start_tv_sec, start_tv_usec);
02400 }
02401 else
02402 {
02403 timeout_milliseconds = -1;
02404
02405 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02406 }
02407
02408
02409
02410 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02411 return;
02412
02413
02414
02415 _dbus_connection_do_iteration_unlocked (connection,
02416 pending,
02417 DBUS_ITERATION_DO_READING |
02418 DBUS_ITERATION_BLOCK,
02419 timeout_milliseconds);
02420
02421 recheck_status:
02422
02423 _dbus_verbose ("top of recheck\n");
02424
02425 HAVE_LOCK_CHECK (connection);
02426
02427
02428
02429 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02430
02431
02432
02433
02434 if (_dbus_pending_call_get_completed_unlocked (pending))
02435 {
02436 _dbus_verbose ("Pending call completed by dispatch\n");
02437 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02438 dbus_pending_call_unref (pending);
02439 return;
02440 }
02441
02442 if (status == DBUS_DISPATCH_DATA_REMAINS)
02443 {
02444 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02445 return;
02446 }
02447
02448 _dbus_get_monotonic_time (&tv_sec, &tv_usec);
02449 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02450 (tv_usec - start_tv_usec) / 1000;
02451
02452 if (!_dbus_connection_get_is_connected_unlocked (connection))
02453 {
02454 DBusMessage *error_msg;
02455
02456 error_msg = generate_local_error_message (client_serial,
02457 DBUS_ERROR_DISCONNECTED,
02458 "Connection was disconnected before a reply was received");
02459
02460
02461 complete_pending_call_and_unlock (connection, pending, error_msg);
02462 dbus_pending_call_unref (pending);
02463 return;
02464 }
02465 else if (connection->disconnect_message_link == NULL)
02466 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02467 else if (timeout == NULL)
02468 {
02469 if (status == DBUS_DISPATCH_NEED_MEMORY)
02470 {
02471
02472
02473
02474
02475 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02476
02477 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02478 }
02479 else
02480 {
02481
02482 _dbus_connection_do_iteration_unlocked (connection,
02483 pending,
02484 DBUS_ITERATION_DO_READING |
02485 DBUS_ITERATION_BLOCK,
02486 timeout_milliseconds - elapsed_milliseconds);
02487 }
02488
02489 goto recheck_status;
02490 }
02491 else if (tv_sec < start_tv_sec)
02492 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02493 else if (elapsed_milliseconds < timeout_milliseconds)
02494 {
02495 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02496
02497 if (status == DBUS_DISPATCH_NEED_MEMORY)
02498 {
02499
02500
02501
02502
02503 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02504
02505 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02506 }
02507 else
02508 {
02509
02510 _dbus_connection_do_iteration_unlocked (connection,
02511 NULL,
02512 DBUS_ITERATION_DO_READING |
02513 DBUS_ITERATION_BLOCK,
02514 timeout_milliseconds - elapsed_milliseconds);
02515 }
02516
02517 goto recheck_status;
02518 }
02519
02520 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02521 elapsed_milliseconds);
02522
02523 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02524
02525
02526 complete_pending_call_and_unlock (connection, pending, NULL);
02527
02528
02529 CONNECTION_LOCK (connection);
02530 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02531 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02532 dbus_pending_call_unref (pending);
02533 }
02534
02571 DBusConnection*
02572 dbus_connection_open (const char *address,
02573 DBusError *error)
02574 {
02575 DBusConnection *connection;
02576
02577 _dbus_return_val_if_fail (address != NULL, NULL);
02578 _dbus_return_val_if_error_is_set (error, NULL);
02579
02580 connection = _dbus_connection_open_internal (address,
02581 TRUE,
02582 error);
02583
02584 return connection;
02585 }
02586
02614 DBusConnection*
02615 dbus_connection_open_private (const char *address,
02616 DBusError *error)
02617 {
02618 DBusConnection *connection;
02619
02620 _dbus_return_val_if_fail (address != NULL, NULL);
02621 _dbus_return_val_if_error_is_set (error, NULL);
02622
02623 connection = _dbus_connection_open_internal (address,
02624 FALSE,
02625 error);
02626
02627 return connection;
02628 }
02629
02636 DBusConnection *
02637 dbus_connection_ref (DBusConnection *connection)
02638 {
02639 dbus_int32_t old_refcount;
02640
02641 _dbus_return_val_if_fail (connection != NULL, NULL);
02642 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02643 old_refcount = _dbus_atomic_inc (&connection->refcount);
02644 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
02645 "ref");
02646
02647 return connection;
02648 }
02649
02650 static void
02651 free_outgoing_message (void *element,
02652 void *data)
02653 {
02654 DBusMessage *message = element;
02655 DBusConnection *connection = data;
02656
02657 _dbus_message_remove_counter (message, connection->outgoing_counter);
02658 dbus_message_unref (message);
02659 }
02660
02661
02662
02663
02664
02665 static void
02666 _dbus_connection_last_unref (DBusConnection *connection)
02667 {
02668 DBusList *link;
02669
02670 _dbus_verbose ("Finalizing connection %p\n", connection);
02671
02672 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02673
02674
02675
02676
02677 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02678 _dbus_assert (connection->server_guid == NULL);
02679
02680
02681 _dbus_object_tree_free_all_unlocked (connection->objects);
02682
02683 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02684 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02685 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02686
02687 _dbus_watch_list_free (connection->watches);
02688 connection->watches = NULL;
02689
02690 _dbus_timeout_list_free (connection->timeouts);
02691 connection->timeouts = NULL;
02692
02693 _dbus_data_slot_list_free (&connection->slot_list);
02694
02695 link = _dbus_list_get_first_link (&connection->filter_list);
02696 while (link != NULL)
02697 {
02698 DBusMessageFilter *filter = link->data;
02699 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02700
02701 filter->function = NULL;
02702 _dbus_message_filter_unref (filter);
02703 link->data = NULL;
02704
02705 link = next;
02706 }
02707 _dbus_list_clear (&connection->filter_list);
02708
02709
02710
02711 _dbus_object_tree_unref (connection->objects);
02712
02713 _dbus_hash_table_unref (connection->pending_replies);
02714 connection->pending_replies = NULL;
02715
02716 _dbus_list_clear (&connection->filter_list);
02717
02718 _dbus_list_foreach (&connection->outgoing_messages,
02719 free_outgoing_message,
02720 connection);
02721 _dbus_list_clear (&connection->outgoing_messages);
02722
02723 _dbus_list_foreach (&connection->incoming_messages,
02724 (DBusForeachFunction) dbus_message_unref,
02725 NULL);
02726 _dbus_list_clear (&connection->incoming_messages);
02727
02728 _dbus_counter_unref (connection->outgoing_counter);
02729
02730 _dbus_transport_unref (connection->transport);
02731
02732 if (connection->disconnect_message_link)
02733 {
02734 DBusMessage *message = connection->disconnect_message_link->data;
02735 dbus_message_unref (message);
02736 _dbus_list_free_link (connection->disconnect_message_link);
02737 }
02738
02739 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02740 _dbus_condvar_free_at_location (&connection->io_path_cond);
02741
02742 _dbus_cmutex_free_at_location (&connection->io_path_mutex);
02743 _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
02744
02745 _dbus_rmutex_free_at_location (&connection->slot_mutex);
02746
02747 _dbus_rmutex_free_at_location (&connection->mutex);
02748
02749 dbus_free (connection);
02750 }
02751
02771 void
02772 dbus_connection_unref (DBusConnection *connection)
02773 {
02774 dbus_int32_t old_refcount;
02775
02776 _dbus_return_if_fail (connection != NULL);
02777 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02778
02779 old_refcount = _dbus_atomic_dec (&connection->refcount);
02780
02781 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
02782 "unref");
02783
02784 if (old_refcount == 1)
02785 {
02786 #ifndef DBUS_DISABLE_CHECKS
02787 if (_dbus_transport_get_is_connected (connection->transport))
02788 {
02789 _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",
02790 connection->shareable ?
02791 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02792 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02793 return;
02794 }
02795 #endif
02796 _dbus_connection_last_unref (connection);
02797 }
02798 }
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809 static void
02810 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02811 {
02812 DBusDispatchStatus status;
02813
02814 HAVE_LOCK_CHECK (connection);
02815
02816 _dbus_verbose ("Disconnecting %p\n", connection);
02817
02818
02819
02820
02821
02822 _dbus_connection_ref_unlocked (connection);
02823
02824 _dbus_transport_disconnect (connection->transport);
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02836
02837
02838 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02839
02840
02841 dbus_connection_unref (connection);
02842 }
02843
02886 void
02887 dbus_connection_close (DBusConnection *connection)
02888 {
02889 _dbus_return_if_fail (connection != NULL);
02890 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02891
02892 CONNECTION_LOCK (connection);
02893
02894 #ifndef DBUS_DISABLE_CHECKS
02895 if (connection->shareable)
02896 {
02897 CONNECTION_UNLOCK (connection);
02898
02899 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02900 return;
02901 }
02902 #endif
02903
02904 _dbus_connection_close_possibly_shared_and_unlock (connection);
02905 }
02906
02907 static dbus_bool_t
02908 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02909 {
02910 HAVE_LOCK_CHECK (connection);
02911 return _dbus_transport_get_is_connected (connection->transport);
02912 }
02913
02927 dbus_bool_t
02928 dbus_connection_get_is_connected (DBusConnection *connection)
02929 {
02930 dbus_bool_t res;
02931
02932 _dbus_return_val_if_fail (connection != NULL, FALSE);
02933
02934 CONNECTION_LOCK (connection);
02935 res = _dbus_connection_get_is_connected_unlocked (connection);
02936 CONNECTION_UNLOCK (connection);
02937
02938 return res;
02939 }
02940
02949 dbus_bool_t
02950 dbus_connection_get_is_authenticated (DBusConnection *connection)
02951 {
02952 dbus_bool_t res;
02953
02954 _dbus_return_val_if_fail (connection != NULL, FALSE);
02955
02956 CONNECTION_LOCK (connection);
02957 res = _dbus_transport_get_is_authenticated (connection->transport);
02958 CONNECTION_UNLOCK (connection);
02959
02960 return res;
02961 }
02962
02983 dbus_bool_t
02984 dbus_connection_get_is_anonymous (DBusConnection *connection)
02985 {
02986 dbus_bool_t res;
02987
02988 _dbus_return_val_if_fail (connection != NULL, FALSE);
02989
02990 CONNECTION_LOCK (connection);
02991 res = _dbus_transport_get_is_anonymous (connection->transport);
02992 CONNECTION_UNLOCK (connection);
02993
02994 return res;
02995 }
02996
03028 char*
03029 dbus_connection_get_server_id (DBusConnection *connection)
03030 {
03031 char *id;
03032
03033 _dbus_return_val_if_fail (connection != NULL, NULL);
03034
03035 CONNECTION_LOCK (connection);
03036 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03037 CONNECTION_UNLOCK (connection);
03038
03039 return id;
03040 }
03041
03059 dbus_bool_t
03060 dbus_connection_can_send_type(DBusConnection *connection,
03061 int type)
03062 {
03063 _dbus_return_val_if_fail (connection != NULL, FALSE);
03064
03065 if (!dbus_type_is_valid (type))
03066 return FALSE;
03067
03068 if (type != DBUS_TYPE_UNIX_FD)
03069 return TRUE;
03070
03071 #ifdef HAVE_UNIX_FD_PASSING
03072 {
03073 dbus_bool_t b;
03074
03075 CONNECTION_LOCK(connection);
03076 b = _dbus_transport_can_pass_unix_fd(connection->transport);
03077 CONNECTION_UNLOCK(connection);
03078
03079 return b;
03080 }
03081 #endif
03082
03083 return FALSE;
03084 }
03085
03099 void
03100 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03101 dbus_bool_t exit_on_disconnect)
03102 {
03103 _dbus_return_if_fail (connection != NULL);
03104
03105 CONNECTION_LOCK (connection);
03106 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03107 CONNECTION_UNLOCK (connection);
03108 }
03109
03119 DBusPreallocatedSend*
03120 dbus_connection_preallocate_send (DBusConnection *connection)
03121 {
03122 DBusPreallocatedSend *preallocated;
03123
03124 _dbus_return_val_if_fail (connection != NULL, NULL);
03125
03126 CONNECTION_LOCK (connection);
03127
03128 preallocated =
03129 _dbus_connection_preallocate_send_unlocked (connection);
03130
03131 CONNECTION_UNLOCK (connection);
03132
03133 return preallocated;
03134 }
03135
03145 void
03146 dbus_connection_free_preallocated_send (DBusConnection *connection,
03147 DBusPreallocatedSend *preallocated)
03148 {
03149 _dbus_return_if_fail (connection != NULL);
03150 _dbus_return_if_fail (preallocated != NULL);
03151 _dbus_return_if_fail (connection == preallocated->connection);
03152
03153 _dbus_list_free_link (preallocated->queue_link);
03154 _dbus_counter_unref (preallocated->counter_link->data);
03155 _dbus_list_free_link (preallocated->counter_link);
03156 dbus_free (preallocated);
03157 }
03158
03171 void
03172 dbus_connection_send_preallocated (DBusConnection *connection,
03173 DBusPreallocatedSend *preallocated,
03174 DBusMessage *message,
03175 dbus_uint32_t *client_serial)
03176 {
03177 _dbus_return_if_fail (connection != NULL);
03178 _dbus_return_if_fail (preallocated != NULL);
03179 _dbus_return_if_fail (message != NULL);
03180 _dbus_return_if_fail (preallocated->connection == connection);
03181 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03182 dbus_message_get_member (message) != NULL);
03183 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03184 (dbus_message_get_interface (message) != NULL &&
03185 dbus_message_get_member (message) != NULL));
03186
03187 CONNECTION_LOCK (connection);
03188
03189 #ifdef HAVE_UNIX_FD_PASSING
03190
03191 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03192 message->n_unix_fds > 0)
03193 {
03194
03195
03196
03197 CONNECTION_UNLOCK (connection);
03198 return;
03199 }
03200
03201 #endif
03202
03203 _dbus_connection_send_preallocated_and_unlock (connection,
03204 preallocated,
03205 message, client_serial);
03206 }
03207
03208 static dbus_bool_t
03209 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03210 DBusMessage *message,
03211 dbus_uint32_t *client_serial)
03212 {
03213 DBusPreallocatedSend *preallocated;
03214
03215 _dbus_assert (connection != NULL);
03216 _dbus_assert (message != NULL);
03217
03218 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03219 if (preallocated == NULL)
03220 return FALSE;
03221
03222 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03223 preallocated,
03224 message,
03225 client_serial);
03226 return TRUE;
03227 }
03228
03256 dbus_bool_t
03257 dbus_connection_send (DBusConnection *connection,
03258 DBusMessage *message,
03259 dbus_uint32_t *serial)
03260 {
03261 _dbus_return_val_if_fail (connection != NULL, FALSE);
03262 _dbus_return_val_if_fail (message != NULL, FALSE);
03263
03264 CONNECTION_LOCK (connection);
03265
03266 #ifdef HAVE_UNIX_FD_PASSING
03267
03268 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03269 message->n_unix_fds > 0)
03270 {
03271
03272
03273
03274 CONNECTION_UNLOCK (connection);
03275 return FALSE;
03276 }
03277
03278 #endif
03279
03280 return _dbus_connection_send_and_unlock (connection,
03281 message,
03282 serial);
03283 }
03284
03285 static dbus_bool_t
03286 reply_handler_timeout (void *data)
03287 {
03288 DBusConnection *connection;
03289 DBusDispatchStatus status;
03290 DBusPendingCall *pending = data;
03291
03292 connection = _dbus_pending_call_get_connection_and_lock (pending);
03293 _dbus_connection_ref_unlocked (connection);
03294
03295 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03296 connection);
03297 _dbus_connection_remove_timeout_unlocked (connection,
03298 _dbus_pending_call_get_timeout_unlocked (pending));
03299 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03300
03301 _dbus_verbose ("middle\n");
03302 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03303
03304
03305 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03306 dbus_connection_unref (connection);
03307
03308 return TRUE;
03309 }
03310
03353 dbus_bool_t
03354 dbus_connection_send_with_reply (DBusConnection *connection,
03355 DBusMessage *message,
03356 DBusPendingCall **pending_return,
03357 int timeout_milliseconds)
03358 {
03359 DBusPendingCall *pending;
03360 dbus_int32_t serial = -1;
03361 DBusDispatchStatus status;
03362
03363 _dbus_return_val_if_fail (connection != NULL, FALSE);
03364 _dbus_return_val_if_fail (message != NULL, FALSE);
03365 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03366
03367 if (pending_return)
03368 *pending_return = NULL;
03369
03370 CONNECTION_LOCK (connection);
03371
03372 #ifdef HAVE_UNIX_FD_PASSING
03373
03374 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03375 message->n_unix_fds > 0)
03376 {
03377
03378
03379
03380
03381 CONNECTION_UNLOCK (connection);
03382 return TRUE;
03383 }
03384
03385 #endif
03386
03387 if (!_dbus_connection_get_is_connected_unlocked (connection))
03388 {
03389 CONNECTION_UNLOCK (connection);
03390
03391 return TRUE;
03392 }
03393
03394 pending = _dbus_pending_call_new_unlocked (connection,
03395 timeout_milliseconds,
03396 reply_handler_timeout);
03397
03398 if (pending == NULL)
03399 {
03400 CONNECTION_UNLOCK (connection);
03401 return FALSE;
03402 }
03403
03404
03405 serial = dbus_message_get_serial (message);
03406 if (serial == 0)
03407 {
03408 serial = _dbus_connection_get_next_client_serial (connection);
03409 dbus_message_set_serial (message, serial);
03410 }
03411
03412 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03413 goto error;
03414
03415
03416
03417
03418
03419 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03420 pending))
03421 goto error;
03422
03423 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03424 {
03425 _dbus_connection_detach_pending_call_and_unlock (connection,
03426 pending);
03427 goto error_unlocked;
03428 }
03429
03430 if (pending_return)
03431 *pending_return = pending;
03432 else
03433 {
03434 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03435
03436
03437
03438 }
03439
03440 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03441
03442
03443 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03444
03445 if (pending_return == NULL)
03446 dbus_pending_call_unref (pending);
03447
03448 return TRUE;
03449
03450 error:
03451 CONNECTION_UNLOCK (connection);
03452 error_unlocked:
03453 dbus_pending_call_unref (pending);
03454 return FALSE;
03455 }
03456
03489 DBusMessage*
03490 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03491 DBusMessage *message,
03492 int timeout_milliseconds,
03493 DBusError *error)
03494 {
03495 DBusMessage *reply;
03496 DBusPendingCall *pending;
03497
03498 _dbus_return_val_if_fail (connection != NULL, NULL);
03499 _dbus_return_val_if_fail (message != NULL, NULL);
03500 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03501 _dbus_return_val_if_error_is_set (error, NULL);
03502
03503 #ifdef HAVE_UNIX_FD_PASSING
03504
03505 CONNECTION_LOCK (connection);
03506 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03507 message->n_unix_fds > 0)
03508 {
03509 CONNECTION_UNLOCK (connection);
03510 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03511 return NULL;
03512 }
03513 CONNECTION_UNLOCK (connection);
03514
03515 #endif
03516
03517 if (!dbus_connection_send_with_reply (connection, message,
03518 &pending, timeout_milliseconds))
03519 {
03520 _DBUS_SET_OOM (error);
03521 return NULL;
03522 }
03523
03524 if (pending == NULL)
03525 {
03526 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03527 return NULL;
03528 }
03529
03530 dbus_pending_call_block (pending);
03531
03532 reply = dbus_pending_call_steal_reply (pending);
03533 dbus_pending_call_unref (pending);
03534
03535
03536
03537
03538 _dbus_assert (reply != NULL);
03539
03540 if (dbus_set_error_from_message (error, reply))
03541 {
03542 dbus_message_unref (reply);
03543 return NULL;
03544 }
03545 else
03546 return reply;
03547 }
03548
03557 static DBusDispatchStatus
03558 _dbus_connection_flush_unlocked (DBusConnection *connection)
03559 {
03560
03561
03562
03563
03564
03565 DBusDispatchStatus status;
03566
03567 HAVE_LOCK_CHECK (connection);
03568
03569 while (connection->n_outgoing > 0 &&
03570 _dbus_connection_get_is_connected_unlocked (connection))
03571 {
03572 _dbus_verbose ("doing iteration in\n");
03573 HAVE_LOCK_CHECK (connection);
03574 _dbus_connection_do_iteration_unlocked (connection,
03575 NULL,
03576 DBUS_ITERATION_DO_READING |
03577 DBUS_ITERATION_DO_WRITING |
03578 DBUS_ITERATION_BLOCK,
03579 -1);
03580 }
03581
03582 HAVE_LOCK_CHECK (connection);
03583 _dbus_verbose ("middle\n");
03584 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03585
03586 HAVE_LOCK_CHECK (connection);
03587 return status;
03588 }
03589
03595 void
03596 dbus_connection_flush (DBusConnection *connection)
03597 {
03598
03599
03600
03601
03602
03603 DBusDispatchStatus status;
03604
03605 _dbus_return_if_fail (connection != NULL);
03606
03607 CONNECTION_LOCK (connection);
03608
03609 status = _dbus_connection_flush_unlocked (connection);
03610
03611 HAVE_LOCK_CHECK (connection);
03612
03613 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03614
03615 _dbus_verbose ("end\n");
03616 }
03617
03628 static dbus_bool_t
03629 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03630 int timeout_milliseconds,
03631 dbus_bool_t dispatch)
03632 {
03633 DBusDispatchStatus dstatus;
03634 dbus_bool_t progress_possible;
03635
03636
03637
03638
03639
03640 dbus_connection_ref (connection);
03641 dstatus = dbus_connection_get_dispatch_status (connection);
03642
03643 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03644 {
03645 _dbus_verbose ("doing dispatch\n");
03646 dbus_connection_dispatch (connection);
03647 CONNECTION_LOCK (connection);
03648 }
03649 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03650 {
03651 _dbus_verbose ("pausing for memory\n");
03652 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03653 CONNECTION_LOCK (connection);
03654 }
03655 else
03656 {
03657 CONNECTION_LOCK (connection);
03658 if (_dbus_connection_get_is_connected_unlocked (connection))
03659 {
03660 _dbus_verbose ("doing iteration\n");
03661 _dbus_connection_do_iteration_unlocked (connection,
03662 NULL,
03663 DBUS_ITERATION_DO_READING |
03664 DBUS_ITERATION_DO_WRITING |
03665 DBUS_ITERATION_BLOCK,
03666 timeout_milliseconds);
03667 }
03668 }
03669
03670 HAVE_LOCK_CHECK (connection);
03671
03672
03673
03674
03675 if (dispatch)
03676 progress_possible = connection->n_incoming != 0 ||
03677 connection->disconnect_message_link != NULL;
03678 else
03679 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03680
03681 CONNECTION_UNLOCK (connection);
03682
03683 dbus_connection_unref (connection);
03684
03685 return progress_possible;
03686 }
03687
03688
03723 dbus_bool_t
03724 dbus_connection_read_write_dispatch (DBusConnection *connection,
03725 int timeout_milliseconds)
03726 {
03727 _dbus_return_val_if_fail (connection != NULL, FALSE);
03728 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03729 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03730 }
03731
03755 dbus_bool_t
03756 dbus_connection_read_write (DBusConnection *connection,
03757 int timeout_milliseconds)
03758 {
03759 _dbus_return_val_if_fail (connection != NULL, FALSE);
03760 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03761 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03762 }
03763
03764
03765
03766
03767
03768
03769 static void
03770 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03771 DBusMessage *head_of_queue)
03772 {
03773 HAVE_LOCK_CHECK (connection);
03774
03775
03776 if (connection->disconnect_message_link == NULL &&
03777 dbus_message_is_signal (head_of_queue,
03778 DBUS_INTERFACE_LOCAL,
03779 "Disconnected"))
03780 {
03781 connection->disconnected_message_arrived = TRUE;
03782 }
03783 }
03784
03804 DBusMessage*
03805 dbus_connection_borrow_message (DBusConnection *connection)
03806 {
03807 DBusDispatchStatus status;
03808 DBusMessage *message;
03809
03810 _dbus_return_val_if_fail (connection != NULL, NULL);
03811
03812 _dbus_verbose ("start\n");
03813
03814
03815
03816
03817 status = dbus_connection_get_dispatch_status (connection);
03818 if (status != DBUS_DISPATCH_DATA_REMAINS)
03819 return NULL;
03820
03821 CONNECTION_LOCK (connection);
03822
03823 _dbus_connection_acquire_dispatch (connection);
03824
03825
03826 _dbus_assert (connection->message_borrowed == NULL);
03827
03828 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03829
03830 message = connection->message_borrowed;
03831
03832 check_disconnected_message_arrived_unlocked (connection, message);
03833
03834
03835 if (message == NULL)
03836 _dbus_connection_release_dispatch (connection);
03837
03838 CONNECTION_UNLOCK (connection);
03839
03840 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
03841
03842
03843
03844 return message;
03845 }
03846
03855 void
03856 dbus_connection_return_message (DBusConnection *connection,
03857 DBusMessage *message)
03858 {
03859 DBusDispatchStatus status;
03860
03861 _dbus_return_if_fail (connection != NULL);
03862 _dbus_return_if_fail (message != NULL);
03863 _dbus_return_if_fail (message == connection->message_borrowed);
03864 _dbus_return_if_fail (connection->dispatch_acquired);
03865
03866 CONNECTION_LOCK (connection);
03867
03868 _dbus_assert (message == connection->message_borrowed);
03869
03870 connection->message_borrowed = NULL;
03871
03872 _dbus_connection_release_dispatch (connection);
03873
03874 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03875 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03876
03877 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
03878 }
03879
03889 void
03890 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03891 DBusMessage *message)
03892 {
03893 DBusMessage *pop_message;
03894 DBusDispatchStatus status;
03895
03896 _dbus_return_if_fail (connection != NULL);
03897 _dbus_return_if_fail (message != NULL);
03898 _dbus_return_if_fail (message == connection->message_borrowed);
03899 _dbus_return_if_fail (connection->dispatch_acquired);
03900
03901 CONNECTION_LOCK (connection);
03902
03903 _dbus_assert (message == connection->message_borrowed);
03904
03905 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03906 _dbus_assert (message == pop_message);
03907 (void) pop_message;
03908
03909 connection->n_incoming -= 1;
03910
03911 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03912 message, connection->n_incoming);
03913
03914 connection->message_borrowed = NULL;
03915
03916 _dbus_connection_release_dispatch (connection);
03917
03918 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03919 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03920 _dbus_message_trace_ref (message, -1, -1,
03921 "dbus_connection_steal_borrowed_message");
03922 }
03923
03924
03925
03926
03927 static DBusList*
03928 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03929 {
03930 HAVE_LOCK_CHECK (connection);
03931
03932 _dbus_assert (connection->message_borrowed == NULL);
03933
03934 if (connection->n_incoming > 0)
03935 {
03936 DBusList *link;
03937
03938 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03939 connection->n_incoming -= 1;
03940
03941 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03942 link->data,
03943 dbus_message_type_to_string (dbus_message_get_type (link->data)),
03944 dbus_message_get_path (link->data) ?
03945 dbus_message_get_path (link->data) :
03946 "no path",
03947 dbus_message_get_interface (link->data) ?
03948 dbus_message_get_interface (link->data) :
03949 "no interface",
03950 dbus_message_get_member (link->data) ?
03951 dbus_message_get_member (link->data) :
03952 "no member",
03953 dbus_message_get_signature (link->data),
03954 connection, connection->n_incoming);
03955
03956 _dbus_message_trace_ref (link->data, -1, -1,
03957 "_dbus_connection_pop_message_link_unlocked");
03958
03959 check_disconnected_message_arrived_unlocked (connection, link->data);
03960
03961 return link;
03962 }
03963 else
03964 return NULL;
03965 }
03966
03967
03968
03969
03970 static DBusMessage*
03971 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03972 {
03973 DBusList *link;
03974
03975 HAVE_LOCK_CHECK (connection);
03976
03977 link = _dbus_connection_pop_message_link_unlocked (connection);
03978
03979 if (link != NULL)
03980 {
03981 DBusMessage *message;
03982
03983 message = link->data;
03984
03985 _dbus_list_free_link (link);
03986
03987 return message;
03988 }
03989 else
03990 return NULL;
03991 }
03992
03993 static void
03994 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03995 DBusList *message_link)
03996 {
03997 HAVE_LOCK_CHECK (connection);
03998
03999 _dbus_assert (message_link != NULL);
04000
04001 _dbus_assert (connection->message_borrowed == NULL);
04002
04003 _dbus_assert (connection->dispatch_acquired);
04004
04005 _dbus_list_prepend_link (&connection->incoming_messages,
04006 message_link);
04007 connection->n_incoming += 1;
04008
04009 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
04010 message_link->data,
04011 dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
04012 dbus_message_get_interface (message_link->data) ?
04013 dbus_message_get_interface (message_link->data) :
04014 "no interface",
04015 dbus_message_get_member (message_link->data) ?
04016 dbus_message_get_member (message_link->data) :
04017 "no member",
04018 dbus_message_get_signature (message_link->data),
04019 connection, connection->n_incoming);
04020
04021 _dbus_message_trace_ref (message_link->data, -1, -1,
04022 "_dbus_connection_putback_message_link_unlocked");
04023 }
04024
04044 DBusMessage*
04045 dbus_connection_pop_message (DBusConnection *connection)
04046 {
04047 DBusMessage *message;
04048 DBusDispatchStatus status;
04049
04050 _dbus_verbose ("start\n");
04051
04052
04053
04054
04055 status = dbus_connection_get_dispatch_status (connection);
04056 if (status != DBUS_DISPATCH_DATA_REMAINS)
04057 return NULL;
04058
04059 CONNECTION_LOCK (connection);
04060 _dbus_connection_acquire_dispatch (connection);
04061 HAVE_LOCK_CHECK (connection);
04062
04063 message = _dbus_connection_pop_message_unlocked (connection);
04064
04065 _dbus_verbose ("Returning popped message %p\n", message);
04066
04067 _dbus_connection_release_dispatch (connection);
04068
04069 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04070 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04071
04072 return message;
04073 }
04074
04082 static void
04083 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04084 {
04085 HAVE_LOCK_CHECK (connection);
04086
04087 _dbus_connection_ref_unlocked (connection);
04088 CONNECTION_UNLOCK (connection);
04089
04090 _dbus_verbose ("locking dispatch_mutex\n");
04091 _dbus_cmutex_lock (connection->dispatch_mutex);
04092
04093 while (connection->dispatch_acquired)
04094 {
04095 _dbus_verbose ("waiting for dispatch to be acquirable\n");
04096 _dbus_condvar_wait (connection->dispatch_cond,
04097 connection->dispatch_mutex);
04098 }
04099
04100 _dbus_assert (!connection->dispatch_acquired);
04101
04102 connection->dispatch_acquired = TRUE;
04103
04104 _dbus_verbose ("unlocking dispatch_mutex\n");
04105 _dbus_cmutex_unlock (connection->dispatch_mutex);
04106
04107 CONNECTION_LOCK (connection);
04108 _dbus_connection_unref_unlocked (connection);
04109 }
04110
04118 static void
04119 _dbus_connection_release_dispatch (DBusConnection *connection)
04120 {
04121 HAVE_LOCK_CHECK (connection);
04122
04123 _dbus_verbose ("locking dispatch_mutex\n");
04124 _dbus_cmutex_lock (connection->dispatch_mutex);
04125
04126 _dbus_assert (connection->dispatch_acquired);
04127
04128 connection->dispatch_acquired = FALSE;
04129 _dbus_condvar_wake_one (connection->dispatch_cond);
04130
04131 _dbus_verbose ("unlocking dispatch_mutex\n");
04132 _dbus_cmutex_unlock (connection->dispatch_mutex);
04133 }
04134
04135 static void
04136 _dbus_connection_failed_pop (DBusConnection *connection,
04137 DBusList *message_link)
04138 {
04139 _dbus_list_prepend_link (&connection->incoming_messages,
04140 message_link);
04141 connection->n_incoming += 1;
04142 }
04143
04144
04145 static void
04146 notify_disconnected_unlocked (DBusConnection *connection)
04147 {
04148 HAVE_LOCK_CHECK (connection);
04149
04150
04151
04152
04153
04154
04155
04156 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04157
04158
04159
04160
04161
04162 if (connection->n_outgoing > 0)
04163 {
04164 DBusList *link;
04165
04166 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04167 connection->n_outgoing);
04168
04169 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04170 {
04171 _dbus_connection_message_sent_unlocked (connection, link->data);
04172 }
04173 }
04174 }
04175
04176
04177 static DBusDispatchStatus
04178 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04179 {
04180 HAVE_LOCK_CHECK (connection);
04181
04182 if (connection->disconnect_message_link != NULL)
04183 {
04184 _dbus_verbose ("Sending disconnect message\n");
04185
04186
04187
04188
04189 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04190
04191
04192
04193
04194 _dbus_connection_queue_synthesized_message_link (connection,
04195 connection->disconnect_message_link);
04196 connection->disconnect_message_link = NULL;
04197
04198 return DBUS_DISPATCH_DATA_REMAINS;
04199 }
04200
04201 return DBUS_DISPATCH_COMPLETE;
04202 }
04203
04204 static DBusDispatchStatus
04205 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04206 {
04207 HAVE_LOCK_CHECK (connection);
04208
04209 if (connection->n_incoming > 0)
04210 return DBUS_DISPATCH_DATA_REMAINS;
04211 else if (!_dbus_transport_queue_messages (connection->transport))
04212 return DBUS_DISPATCH_NEED_MEMORY;
04213 else
04214 {
04215 DBusDispatchStatus status;
04216 dbus_bool_t is_connected;
04217
04218 status = _dbus_transport_get_dispatch_status (connection->transport);
04219 is_connected = _dbus_transport_get_is_connected (connection->transport);
04220
04221 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04222 DISPATCH_STATUS_NAME (status), is_connected);
04223
04224 if (!is_connected)
04225 {
04226
04227
04228
04229
04230
04231
04232 notify_disconnected_unlocked (connection);
04233
04234
04235
04236
04237
04238
04239 if (status == DBUS_DISPATCH_COMPLETE)
04240 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04241 }
04242
04243 if (status != DBUS_DISPATCH_COMPLETE)
04244 return status;
04245 else if (connection->n_incoming > 0)
04246 return DBUS_DISPATCH_DATA_REMAINS;
04247 else
04248 return DBUS_DISPATCH_COMPLETE;
04249 }
04250 }
04251
04252 static void
04253 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04254 DBusDispatchStatus new_status)
04255 {
04256 dbus_bool_t changed;
04257 DBusDispatchStatusFunction function;
04258 void *data;
04259
04260 HAVE_LOCK_CHECK (connection);
04261
04262 _dbus_connection_ref_unlocked (connection);
04263
04264 changed = new_status != connection->last_dispatch_status;
04265
04266 connection->last_dispatch_status = new_status;
04267
04268 function = connection->dispatch_status_function;
04269 data = connection->dispatch_status_data;
04270
04271 if (connection->disconnected_message_arrived &&
04272 !connection->disconnected_message_processed)
04273 {
04274 connection->disconnected_message_processed = TRUE;
04275
04276
04277
04278
04279
04280 connection_forget_shared_unlocked (connection);
04281
04282 if (connection->exit_on_disconnect)
04283 {
04284 CONNECTION_UNLOCK (connection);
04285
04286 _dbus_verbose ("Exiting on Disconnected signal\n");
04287 _dbus_exit (1);
04288 _dbus_assert_not_reached ("Call to exit() returned");
04289 }
04290 }
04291
04292
04293 CONNECTION_UNLOCK (connection);
04294
04295 if (changed && function)
04296 {
04297 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04298 connection, new_status,
04299 DISPATCH_STATUS_NAME (new_status));
04300 (* function) (connection, new_status, data);
04301 }
04302
04303 dbus_connection_unref (connection);
04304 }
04305
04331 DBusDispatchStatus
04332 dbus_connection_get_dispatch_status (DBusConnection *connection)
04333 {
04334 DBusDispatchStatus status;
04335
04336 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04337
04338 _dbus_verbose ("start\n");
04339
04340 CONNECTION_LOCK (connection);
04341
04342 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04343
04344 CONNECTION_UNLOCK (connection);
04345
04346 return status;
04347 }
04348
04352 static DBusHandlerResult
04353 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04354 DBusMessage *message)
04355 {
04356 dbus_bool_t sent = FALSE;
04357 DBusMessage *ret = NULL;
04358 DBusList *expire_link;
04359
04360 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04361 {
04362
04363 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04364 }
04365
04366 if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04367 {
04368 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04369 }
04370
04371
04372
04373 expire_link = _dbus_list_alloc_link (NULL);
04374
04375 if (!expire_link)
04376 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04377
04378 if (dbus_message_is_method_call (message,
04379 DBUS_INTERFACE_PEER,
04380 "Ping"))
04381 {
04382 ret = dbus_message_new_method_return (message);
04383 if (ret == NULL)
04384 goto out;
04385
04386 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04387 }
04388 else if (dbus_message_is_method_call (message,
04389 DBUS_INTERFACE_PEER,
04390 "GetMachineId"))
04391 {
04392 DBusString uuid;
04393
04394 ret = dbus_message_new_method_return (message);
04395 if (ret == NULL)
04396 goto out;
04397
04398 _dbus_string_init (&uuid);
04399 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04400 {
04401 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04402 if (dbus_message_append_args (ret,
04403 DBUS_TYPE_STRING, &v_STRING,
04404 DBUS_TYPE_INVALID))
04405 {
04406 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04407 }
04408 }
04409 _dbus_string_free (&uuid);
04410 }
04411 else
04412 {
04413
04414
04415
04416
04417 ret = dbus_message_new_error (message,
04418 DBUS_ERROR_UNKNOWN_METHOD,
04419 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04420 if (ret == NULL)
04421 goto out;
04422
04423 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04424 }
04425
04426 out:
04427 if (ret == NULL)
04428 {
04429 _dbus_list_free_link (expire_link);
04430 }
04431 else
04432 {
04433
04434 expire_link->data = ret;
04435 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04436 }
04437
04438 if (!sent)
04439 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04440
04441 return DBUS_HANDLER_RESULT_HANDLED;
04442 }
04443
04450 static DBusHandlerResult
04451 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04452 DBusMessage *message)
04453 {
04454
04455
04456
04457 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04458 }
04459
04502 DBusDispatchStatus
04503 dbus_connection_dispatch (DBusConnection *connection)
04504 {
04505 DBusMessage *message;
04506 DBusList *link, *filter_list_copy, *message_link;
04507 DBusHandlerResult result;
04508 DBusPendingCall *pending;
04509 dbus_int32_t reply_serial;
04510 DBusDispatchStatus status;
04511 dbus_bool_t found_object;
04512
04513 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04514
04515 _dbus_verbose ("\n");
04516
04517 CONNECTION_LOCK (connection);
04518 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04519 if (status != DBUS_DISPATCH_DATA_REMAINS)
04520 {
04521
04522 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04523 return status;
04524 }
04525
04526
04527
04528
04529 _dbus_connection_ref_unlocked (connection);
04530
04531 _dbus_connection_acquire_dispatch (connection);
04532 HAVE_LOCK_CHECK (connection);
04533
04534 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04535 if (message_link == NULL)
04536 {
04537
04538
04539 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04540
04541 _dbus_connection_release_dispatch (connection);
04542
04543 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04544
04545 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04546
04547 dbus_connection_unref (connection);
04548
04549 return status;
04550 }
04551
04552 message = message_link->data;
04553
04554 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04555 message,
04556 dbus_message_type_to_string (dbus_message_get_type (message)),
04557 dbus_message_get_interface (message) ?
04558 dbus_message_get_interface (message) :
04559 "no interface",
04560 dbus_message_get_member (message) ?
04561 dbus_message_get_member (message) :
04562 "no member",
04563 dbus_message_get_signature (message));
04564
04565 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04566
04567
04568
04569
04570
04571
04572
04573
04574 reply_serial = dbus_message_get_reply_serial (message);
04575 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04576 reply_serial);
04577 if (pending)
04578 {
04579 _dbus_verbose ("Dispatching a pending reply\n");
04580 complete_pending_call_and_unlock (connection, pending, message);
04581 pending = NULL;
04582
04583 CONNECTION_LOCK (connection);
04584 _dbus_verbose ("pending call completed in dispatch\n");
04585 result = DBUS_HANDLER_RESULT_HANDLED;
04586 goto out;
04587 }
04588
04589 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04590 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04591 goto out;
04592
04593 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04594 {
04595 _dbus_connection_release_dispatch (connection);
04596 HAVE_LOCK_CHECK (connection);
04597
04598 _dbus_connection_failed_pop (connection, message_link);
04599
04600
04601 _dbus_connection_update_dispatch_status_and_unlock (connection,
04602 DBUS_DISPATCH_NEED_MEMORY);
04603 dbus_connection_unref (connection);
04604
04605 return DBUS_DISPATCH_NEED_MEMORY;
04606 }
04607
04608 _dbus_list_foreach (&filter_list_copy,
04609 (DBusForeachFunction)_dbus_message_filter_ref,
04610 NULL);
04611
04612
04613
04614
04615 CONNECTION_UNLOCK (connection);
04616
04617 link = _dbus_list_get_first_link (&filter_list_copy);
04618 while (link != NULL)
04619 {
04620 DBusMessageFilter *filter = link->data;
04621 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04622
04623 if (filter->function == NULL)
04624 {
04625 _dbus_verbose (" filter was removed in a callback function\n");
04626 link = next;
04627 continue;
04628 }
04629
04630 _dbus_verbose (" running filter on message %p\n", message);
04631 result = (* filter->function) (connection, message, filter->user_data);
04632
04633 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04634 break;
04635
04636 link = next;
04637 }
04638
04639 _dbus_list_foreach (&filter_list_copy,
04640 (DBusForeachFunction)_dbus_message_filter_unref,
04641 NULL);
04642 _dbus_list_clear (&filter_list_copy);
04643
04644 CONNECTION_LOCK (connection);
04645
04646 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04647 {
04648 _dbus_verbose ("No memory\n");
04649 goto out;
04650 }
04651 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04652 {
04653 _dbus_verbose ("filter handled message in dispatch\n");
04654 goto out;
04655 }
04656
04657
04658
04659
04660 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
04661 message,
04662 dbus_message_type_to_string (dbus_message_get_type (message)),
04663 dbus_message_get_interface (message) ?
04664 dbus_message_get_interface (message) :
04665 "no interface",
04666 dbus_message_get_member (message) ?
04667 dbus_message_get_member (message) :
04668 "no member",
04669 dbus_message_get_signature (message));
04670
04671 HAVE_LOCK_CHECK (connection);
04672 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04673 message,
04674 &found_object);
04675
04676 CONNECTION_LOCK (connection);
04677
04678 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04679 {
04680 _dbus_verbose ("object tree handled message in dispatch\n");
04681 goto out;
04682 }
04683
04684 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04685 {
04686 DBusMessage *reply;
04687 DBusString str;
04688 DBusPreallocatedSend *preallocated;
04689 DBusList *expire_link;
04690
04691 _dbus_verbose (" sending error %s\n",
04692 DBUS_ERROR_UNKNOWN_METHOD);
04693
04694 if (!_dbus_string_init (&str))
04695 {
04696 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04697 _dbus_verbose ("no memory for error string in dispatch\n");
04698 goto out;
04699 }
04700
04701 if (!_dbus_string_append_printf (&str,
04702 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04703 dbus_message_get_member (message),
04704 dbus_message_get_signature (message),
04705 dbus_message_get_interface (message)))
04706 {
04707 _dbus_string_free (&str);
04708 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04709 _dbus_verbose ("no memory for error string in dispatch\n");
04710 goto out;
04711 }
04712
04713 reply = dbus_message_new_error (message,
04714 found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
04715 _dbus_string_get_const_data (&str));
04716 _dbus_string_free (&str);
04717
04718 if (reply == NULL)
04719 {
04720 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04721 _dbus_verbose ("no memory for error reply in dispatch\n");
04722 goto out;
04723 }
04724
04725 expire_link = _dbus_list_alloc_link (reply);
04726
04727 if (expire_link == NULL)
04728 {
04729 dbus_message_unref (reply);
04730 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04731 _dbus_verbose ("no memory for error send in dispatch\n");
04732 goto out;
04733 }
04734
04735 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04736
04737 if (preallocated == NULL)
04738 {
04739 _dbus_list_free_link (expire_link);
04740
04741
04742 dbus_message_unref (reply);
04743 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04744 _dbus_verbose ("no memory for error send in dispatch\n");
04745 goto out;
04746 }
04747
04748 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04749 reply, NULL);
04750
04751 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04752
04753 result = DBUS_HANDLER_RESULT_HANDLED;
04754 }
04755
04756 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04757 dbus_message_type_to_string (dbus_message_get_type (message)),
04758 dbus_message_get_interface (message) ?
04759 dbus_message_get_interface (message) :
04760 "no interface",
04761 dbus_message_get_member (message) ?
04762 dbus_message_get_member (message) :
04763 "no member",
04764 dbus_message_get_signature (message),
04765 connection);
04766
04767 out:
04768 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04769 {
04770 _dbus_verbose ("out of memory\n");
04771
04772
04773
04774
04775
04776 _dbus_connection_putback_message_link_unlocked (connection,
04777 message_link);
04778
04779 message_link = NULL;
04780 message = NULL;
04781 }
04782 else
04783 {
04784 _dbus_verbose (" ... done dispatching\n");
04785 }
04786
04787 _dbus_connection_release_dispatch (connection);
04788 HAVE_LOCK_CHECK (connection);
04789
04790 if (message != NULL)
04791 {
04792
04793
04794
04795
04796
04797
04798
04799 CONNECTION_UNLOCK (connection);
04800 dbus_message_unref (message);
04801 CONNECTION_LOCK (connection);
04802 }
04803
04804 if (message_link != NULL)
04805 _dbus_list_free_link (message_link);
04806
04807 _dbus_verbose ("before final status update\n");
04808 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04809
04810
04811 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04812
04813 dbus_connection_unref (connection);
04814
04815 return status;
04816 }
04817
04879 dbus_bool_t
04880 dbus_connection_set_watch_functions (DBusConnection *connection,
04881 DBusAddWatchFunction add_function,
04882 DBusRemoveWatchFunction remove_function,
04883 DBusWatchToggledFunction toggled_function,
04884 void *data,
04885 DBusFreeFunction free_data_function)
04886 {
04887 dbus_bool_t retval;
04888
04889 _dbus_return_val_if_fail (connection != NULL, FALSE);
04890
04891 CONNECTION_LOCK (connection);
04892
04893 retval = _dbus_watch_list_set_functions (connection->watches,
04894 add_function, remove_function,
04895 toggled_function,
04896 data, free_data_function);
04897
04898 CONNECTION_UNLOCK (connection);
04899
04900 return retval;
04901 }
04902
04942 dbus_bool_t
04943 dbus_connection_set_timeout_functions (DBusConnection *connection,
04944 DBusAddTimeoutFunction add_function,
04945 DBusRemoveTimeoutFunction remove_function,
04946 DBusTimeoutToggledFunction toggled_function,
04947 void *data,
04948 DBusFreeFunction free_data_function)
04949 {
04950 dbus_bool_t retval;
04951
04952 _dbus_return_val_if_fail (connection != NULL, FALSE);
04953
04954 CONNECTION_LOCK (connection);
04955
04956 retval = _dbus_timeout_list_set_functions (connection->timeouts,
04957 add_function, remove_function,
04958 toggled_function,
04959 data, free_data_function);
04960
04961 CONNECTION_UNLOCK (connection);
04962
04963 return retval;
04964 }
04965
04980 void
04981 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04982 DBusWakeupMainFunction wakeup_main_function,
04983 void *data,
04984 DBusFreeFunction free_data_function)
04985 {
04986 void *old_data;
04987 DBusFreeFunction old_free_data;
04988
04989 _dbus_return_if_fail (connection != NULL);
04990
04991 CONNECTION_LOCK (connection);
04992 old_data = connection->wakeup_main_data;
04993 old_free_data = connection->free_wakeup_main_data;
04994
04995 connection->wakeup_main_function = wakeup_main_function;
04996 connection->wakeup_main_data = data;
04997 connection->free_wakeup_main_data = free_data_function;
04998
04999 CONNECTION_UNLOCK (connection);
05000
05001
05002 if (old_free_data)
05003 (*old_free_data) (old_data);
05004 }
05005
05026 void
05027 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
05028 DBusDispatchStatusFunction function,
05029 void *data,
05030 DBusFreeFunction free_data_function)
05031 {
05032 void *old_data;
05033 DBusFreeFunction old_free_data;
05034
05035 _dbus_return_if_fail (connection != NULL);
05036
05037 CONNECTION_LOCK (connection);
05038 old_data = connection->dispatch_status_data;
05039 old_free_data = connection->free_dispatch_status_data;
05040
05041 connection->dispatch_status_function = function;
05042 connection->dispatch_status_data = data;
05043 connection->free_dispatch_status_data = free_data_function;
05044
05045 CONNECTION_UNLOCK (connection);
05046
05047
05048 if (old_free_data)
05049 (*old_free_data) (old_data);
05050 }
05051
05071 dbus_bool_t
05072 dbus_connection_get_unix_fd (DBusConnection *connection,
05073 int *fd)
05074 {
05075 _dbus_return_val_if_fail (connection != NULL, FALSE);
05076 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05077
05078 #ifdef DBUS_WIN
05079
05080 return FALSE;
05081 #endif
05082
05083 return dbus_connection_get_socket(connection, fd);
05084 }
05085
05101 dbus_bool_t
05102 dbus_connection_get_socket(DBusConnection *connection,
05103 int *fd)
05104 {
05105 dbus_bool_t retval;
05106
05107 _dbus_return_val_if_fail (connection != NULL, FALSE);
05108 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05109
05110 CONNECTION_LOCK (connection);
05111
05112 retval = _dbus_transport_get_socket_fd (connection->transport,
05113 fd);
05114
05115 CONNECTION_UNLOCK (connection);
05116
05117 return retval;
05118 }
05119
05120
05143 dbus_bool_t
05144 dbus_connection_get_unix_user (DBusConnection *connection,
05145 unsigned long *uid)
05146 {
05147 dbus_bool_t result;
05148
05149 _dbus_return_val_if_fail (connection != NULL, FALSE);
05150 _dbus_return_val_if_fail (uid != NULL, FALSE);
05151
05152 CONNECTION_LOCK (connection);
05153
05154 if (!_dbus_transport_get_is_authenticated (connection->transport))
05155 result = FALSE;
05156 else
05157 result = _dbus_transport_get_unix_user (connection->transport,
05158 uid);
05159
05160 #ifdef DBUS_WIN
05161 _dbus_assert (!result);
05162 #endif
05163
05164 CONNECTION_UNLOCK (connection);
05165
05166 return result;
05167 }
05168
05179 dbus_bool_t
05180 dbus_connection_get_unix_process_id (DBusConnection *connection,
05181 unsigned long *pid)
05182 {
05183 dbus_bool_t result;
05184
05185 _dbus_return_val_if_fail (connection != NULL, FALSE);
05186 _dbus_return_val_if_fail (pid != NULL, FALSE);
05187
05188 CONNECTION_LOCK (connection);
05189
05190 if (!_dbus_transport_get_is_authenticated (connection->transport))
05191 result = FALSE;
05192 else
05193 result = _dbus_transport_get_unix_process_id (connection->transport,
05194 pid);
05195
05196 CONNECTION_UNLOCK (connection);
05197
05198 return result;
05199 }
05200
05211 dbus_bool_t
05212 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05213 void **data,
05214 dbus_int32_t *data_size)
05215 {
05216 dbus_bool_t result;
05217
05218 _dbus_return_val_if_fail (connection != NULL, FALSE);
05219 _dbus_return_val_if_fail (data != NULL, FALSE);
05220 _dbus_return_val_if_fail (data_size != NULL, FALSE);
05221
05222 CONNECTION_LOCK (connection);
05223
05224 if (!_dbus_transport_get_is_authenticated (connection->transport))
05225 result = FALSE;
05226 else
05227 result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05228 data,
05229 data_size);
05230 CONNECTION_UNLOCK (connection);
05231
05232 return result;
05233 }
05234
05257 void
05258 dbus_connection_set_unix_user_function (DBusConnection *connection,
05259 DBusAllowUnixUserFunction function,
05260 void *data,
05261 DBusFreeFunction free_data_function)
05262 {
05263 void *old_data = NULL;
05264 DBusFreeFunction old_free_function = NULL;
05265
05266 _dbus_return_if_fail (connection != NULL);
05267
05268 CONNECTION_LOCK (connection);
05269 _dbus_transport_set_unix_user_function (connection->transport,
05270 function, data, free_data_function,
05271 &old_data, &old_free_function);
05272 CONNECTION_UNLOCK (connection);
05273
05274 if (old_free_function != NULL)
05275 (* old_free_function) (old_data);
05276 }
05277
05309 dbus_bool_t
05310 dbus_connection_get_windows_user (DBusConnection *connection,
05311 char **windows_sid_p)
05312 {
05313 dbus_bool_t result;
05314
05315 _dbus_return_val_if_fail (connection != NULL, FALSE);
05316 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05317
05318 CONNECTION_LOCK (connection);
05319
05320 if (!_dbus_transport_get_is_authenticated (connection->transport))
05321 result = FALSE;
05322 else
05323 result = _dbus_transport_get_windows_user (connection->transport,
05324 windows_sid_p);
05325
05326 #ifdef DBUS_UNIX
05327 _dbus_assert (!result);
05328 #endif
05329
05330 CONNECTION_UNLOCK (connection);
05331
05332 return result;
05333 }
05334
05356 void
05357 dbus_connection_set_windows_user_function (DBusConnection *connection,
05358 DBusAllowWindowsUserFunction function,
05359 void *data,
05360 DBusFreeFunction free_data_function)
05361 {
05362 void *old_data = NULL;
05363 DBusFreeFunction old_free_function = NULL;
05364
05365 _dbus_return_if_fail (connection != NULL);
05366
05367 CONNECTION_LOCK (connection);
05368 _dbus_transport_set_windows_user_function (connection->transport,
05369 function, data, free_data_function,
05370 &old_data, &old_free_function);
05371 CONNECTION_UNLOCK (connection);
05372
05373 if (old_free_function != NULL)
05374 (* old_free_function) (old_data);
05375 }
05376
05403 void
05404 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05405 dbus_bool_t value)
05406 {
05407 _dbus_return_if_fail (connection != NULL);
05408
05409 CONNECTION_LOCK (connection);
05410 _dbus_transport_set_allow_anonymous (connection->transport, value);
05411 CONNECTION_UNLOCK (connection);
05412 }
05413
05431 void
05432 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05433 dbus_bool_t value)
05434 {
05435 _dbus_return_if_fail (connection != NULL);
05436
05437 CONNECTION_LOCK (connection);
05438 connection->route_peer_messages = TRUE;
05439 CONNECTION_UNLOCK (connection);
05440 }
05441
05463 dbus_bool_t
05464 dbus_connection_add_filter (DBusConnection *connection,
05465 DBusHandleMessageFunction function,
05466 void *user_data,
05467 DBusFreeFunction free_data_function)
05468 {
05469 DBusMessageFilter *filter;
05470
05471 _dbus_return_val_if_fail (connection != NULL, FALSE);
05472 _dbus_return_val_if_fail (function != NULL, FALSE);
05473
05474 filter = dbus_new0 (DBusMessageFilter, 1);
05475 if (filter == NULL)
05476 return FALSE;
05477
05478 _dbus_atomic_inc (&filter->refcount);
05479
05480 CONNECTION_LOCK (connection);
05481
05482 if (!_dbus_list_append (&connection->filter_list,
05483 filter))
05484 {
05485 _dbus_message_filter_unref (filter);
05486 CONNECTION_UNLOCK (connection);
05487 return FALSE;
05488 }
05489
05490
05491
05492
05493
05494
05495 filter->function = function;
05496 filter->user_data = user_data;
05497 filter->free_user_data_function = free_data_function;
05498
05499 CONNECTION_UNLOCK (connection);
05500 return TRUE;
05501 }
05502
05515 void
05516 dbus_connection_remove_filter (DBusConnection *connection,
05517 DBusHandleMessageFunction function,
05518 void *user_data)
05519 {
05520 DBusList *link;
05521 DBusMessageFilter *filter;
05522
05523 _dbus_return_if_fail (connection != NULL);
05524 _dbus_return_if_fail (function != NULL);
05525
05526 CONNECTION_LOCK (connection);
05527
05528 filter = NULL;
05529
05530 link = _dbus_list_get_last_link (&connection->filter_list);
05531 while (link != NULL)
05532 {
05533 filter = link->data;
05534
05535 if (filter->function == function &&
05536 filter->user_data == user_data)
05537 {
05538 _dbus_list_remove_link (&connection->filter_list, link);
05539 filter->function = NULL;
05540
05541 break;
05542 }
05543
05544 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05545 filter = NULL;
05546 }
05547
05548 CONNECTION_UNLOCK (connection);
05549
05550 #ifndef DBUS_DISABLE_CHECKS
05551 if (filter == NULL)
05552 {
05553 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05554 function, user_data);
05555 return;
05556 }
05557 #endif
05558
05559
05560 if (filter->free_user_data_function)
05561 (* filter->free_user_data_function) (filter->user_data);
05562
05563 filter->free_user_data_function = NULL;
05564 filter->user_data = NULL;
05565
05566 _dbus_message_filter_unref (filter);
05567 }
05568
05584 static dbus_bool_t
05585 _dbus_connection_register_object_path (DBusConnection *connection,
05586 dbus_bool_t fallback,
05587 const char *path,
05588 const DBusObjectPathVTable *vtable,
05589 void *user_data,
05590 DBusError *error)
05591 {
05592 char **decomposed_path;
05593 dbus_bool_t retval;
05594
05595 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05596 return FALSE;
05597
05598 CONNECTION_LOCK (connection);
05599
05600 retval = _dbus_object_tree_register (connection->objects,
05601 fallback,
05602 (const char **) decomposed_path, vtable,
05603 user_data, error);
05604
05605 CONNECTION_UNLOCK (connection);
05606
05607 dbus_free_string_array (decomposed_path);
05608
05609 return retval;
05610 }
05611
05624 dbus_bool_t
05625 dbus_connection_try_register_object_path (DBusConnection *connection,
05626 const char *path,
05627 const DBusObjectPathVTable *vtable,
05628 void *user_data,
05629 DBusError *error)
05630 {
05631 _dbus_return_val_if_fail (connection != NULL, FALSE);
05632 _dbus_return_val_if_fail (path != NULL, FALSE);
05633 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05634 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05635
05636 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
05637 }
05638
05654 dbus_bool_t
05655 dbus_connection_register_object_path (DBusConnection *connection,
05656 const char *path,
05657 const DBusObjectPathVTable *vtable,
05658 void *user_data)
05659 {
05660 dbus_bool_t retval;
05661 DBusError error = DBUS_ERROR_INIT;
05662
05663 _dbus_return_val_if_fail (connection != NULL, FALSE);
05664 _dbus_return_val_if_fail (path != NULL, FALSE);
05665 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05666 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05667
05668 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
05669
05670 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05671 {
05672 _dbus_warn ("%s\n", error.message);
05673 dbus_error_free (&error);
05674 return FALSE;
05675 }
05676
05677 return retval;
05678 }
05679
05694 dbus_bool_t
05695 dbus_connection_try_register_fallback (DBusConnection *connection,
05696 const char *path,
05697 const DBusObjectPathVTable *vtable,
05698 void *user_data,
05699 DBusError *error)
05700 {
05701 _dbus_return_val_if_fail (connection != NULL, FALSE);
05702 _dbus_return_val_if_fail (path != NULL, FALSE);
05703 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05704 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05705
05706 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
05707 }
05708
05726 dbus_bool_t
05727 dbus_connection_register_fallback (DBusConnection *connection,
05728 const char *path,
05729 const DBusObjectPathVTable *vtable,
05730 void *user_data)
05731 {
05732 dbus_bool_t retval;
05733 DBusError error = DBUS_ERROR_INIT;
05734
05735 _dbus_return_val_if_fail (connection != NULL, FALSE);
05736 _dbus_return_val_if_fail (path != NULL, FALSE);
05737 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05738 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05739
05740 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
05741
05742 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05743 {
05744 _dbus_warn ("%s\n", error.message);
05745 dbus_error_free (&error);
05746 return FALSE;
05747 }
05748
05749 return retval;
05750 }
05751
05761 dbus_bool_t
05762 dbus_connection_unregister_object_path (DBusConnection *connection,
05763 const char *path)
05764 {
05765 char **decomposed_path;
05766
05767 _dbus_return_val_if_fail (connection != NULL, FALSE);
05768 _dbus_return_val_if_fail (path != NULL, FALSE);
05769 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05770
05771 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05772 return FALSE;
05773
05774 CONNECTION_LOCK (connection);
05775
05776 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05777
05778 dbus_free_string_array (decomposed_path);
05779
05780 return TRUE;
05781 }
05782
05793 dbus_bool_t
05794 dbus_connection_get_object_path_data (DBusConnection *connection,
05795 const char *path,
05796 void **data_p)
05797 {
05798 char **decomposed_path;
05799
05800 _dbus_return_val_if_fail (connection != NULL, FALSE);
05801 _dbus_return_val_if_fail (path != NULL, FALSE);
05802 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05803
05804 *data_p = NULL;
05805
05806 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05807 return FALSE;
05808
05809 CONNECTION_LOCK (connection);
05810
05811 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05812
05813 CONNECTION_UNLOCK (connection);
05814
05815 dbus_free_string_array (decomposed_path);
05816
05817 return TRUE;
05818 }
05819
05830 dbus_bool_t
05831 dbus_connection_list_registered (DBusConnection *connection,
05832 const char *parent_path,
05833 char ***child_entries)
05834 {
05835 char **decomposed_path;
05836 dbus_bool_t retval;
05837 _dbus_return_val_if_fail (connection != NULL, FALSE);
05838 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05839 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05840 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05841
05842 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05843 return FALSE;
05844
05845 CONNECTION_LOCK (connection);
05846
05847 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05848 (const char **) decomposed_path,
05849 child_entries);
05850 dbus_free_string_array (decomposed_path);
05851
05852 return retval;
05853 }
05854
05855 static DBusDataSlotAllocator slot_allocator;
05856 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05857
05872 dbus_bool_t
05873 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05874 {
05875 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05876 &_DBUS_LOCK_NAME (connection_slots),
05877 slot_p);
05878 }
05879
05891 void
05892 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05893 {
05894 _dbus_return_if_fail (*slot_p >= 0);
05895
05896 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05897 }
05898
05921 dbus_bool_t
05922 dbus_connection_set_data (DBusConnection *connection,
05923 dbus_int32_t slot,
05924 void *data,
05925 DBusFreeFunction free_data_func)
05926 {
05927 DBusFreeFunction old_free_func;
05928 void *old_data;
05929 dbus_bool_t retval;
05930
05931 _dbus_return_val_if_fail (connection != NULL, FALSE);
05932 _dbus_return_val_if_fail (slot >= 0, FALSE);
05933
05934 SLOTS_LOCK (connection);
05935
05936 retval = _dbus_data_slot_list_set (&slot_allocator,
05937 &connection->slot_list,
05938 slot, data, free_data_func,
05939 &old_free_func, &old_data);
05940
05941 SLOTS_UNLOCK (connection);
05942
05943 if (retval)
05944 {
05945
05946 if (old_free_func)
05947 (* old_free_func) (old_data);
05948 }
05949
05950 return retval;
05951 }
05952
05970 void*
05971 dbus_connection_get_data (DBusConnection *connection,
05972 dbus_int32_t slot)
05973 {
05974 void *res;
05975
05976 _dbus_return_val_if_fail (connection != NULL, NULL);
05977 _dbus_return_val_if_fail (slot >= 0, NULL);
05978
05979 SLOTS_LOCK (connection);
05980
05981 res = _dbus_data_slot_list_get (&slot_allocator,
05982 &connection->slot_list,
05983 slot);
05984
05985 SLOTS_UNLOCK (connection);
05986
05987 return res;
05988 }
05989
05996 void
05997 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05998 {
05999 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
06000 }
06001
06010 void
06011 dbus_connection_set_max_message_size (DBusConnection *connection,
06012 long size)
06013 {
06014 _dbus_return_if_fail (connection != NULL);
06015
06016 CONNECTION_LOCK (connection);
06017 _dbus_transport_set_max_message_size (connection->transport,
06018 size);
06019 CONNECTION_UNLOCK (connection);
06020 }
06021
06028 long
06029 dbus_connection_get_max_message_size (DBusConnection *connection)
06030 {
06031 long res;
06032
06033 _dbus_return_val_if_fail (connection != NULL, 0);
06034
06035 CONNECTION_LOCK (connection);
06036 res = _dbus_transport_get_max_message_size (connection->transport);
06037 CONNECTION_UNLOCK (connection);
06038 return res;
06039 }
06040
06049 void
06050 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06051 long n)
06052 {
06053 _dbus_return_if_fail (connection != NULL);
06054
06055 CONNECTION_LOCK (connection);
06056 _dbus_transport_set_max_message_unix_fds (connection->transport,
06057 n);
06058 CONNECTION_UNLOCK (connection);
06059 }
06060
06067 long
06068 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06069 {
06070 long res;
06071
06072 _dbus_return_val_if_fail (connection != NULL, 0);
06073
06074 CONNECTION_LOCK (connection);
06075 res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06076 CONNECTION_UNLOCK (connection);
06077 return res;
06078 }
06079
06105 void
06106 dbus_connection_set_max_received_size (DBusConnection *connection,
06107 long size)
06108 {
06109 _dbus_return_if_fail (connection != NULL);
06110
06111 CONNECTION_LOCK (connection);
06112 _dbus_transport_set_max_received_size (connection->transport,
06113 size);
06114 CONNECTION_UNLOCK (connection);
06115 }
06116
06123 long
06124 dbus_connection_get_max_received_size (DBusConnection *connection)
06125 {
06126 long res;
06127
06128 _dbus_return_val_if_fail (connection != NULL, 0);
06129
06130 CONNECTION_LOCK (connection);
06131 res = _dbus_transport_get_max_received_size (connection->transport);
06132 CONNECTION_UNLOCK (connection);
06133 return res;
06134 }
06135
06147 void
06148 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06149 long n)
06150 {
06151 _dbus_return_if_fail (connection != NULL);
06152
06153 CONNECTION_LOCK (connection);
06154 _dbus_transport_set_max_received_unix_fds (connection->transport,
06155 n);
06156 CONNECTION_UNLOCK (connection);
06157 }
06158
06165 long
06166 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06167 {
06168 long res;
06169
06170 _dbus_return_val_if_fail (connection != NULL, 0);
06171
06172 CONNECTION_LOCK (connection);
06173 res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06174 CONNECTION_UNLOCK (connection);
06175 return res;
06176 }
06177
06188 long
06189 dbus_connection_get_outgoing_size (DBusConnection *connection)
06190 {
06191 long res;
06192
06193 _dbus_return_val_if_fail (connection != NULL, 0);
06194
06195 CONNECTION_LOCK (connection);
06196 res = _dbus_counter_get_size_value (connection->outgoing_counter);
06197 CONNECTION_UNLOCK (connection);
06198 return res;
06199 }
06200
06201 #ifdef DBUS_ENABLE_STATS
06202 void
06203 _dbus_connection_get_stats (DBusConnection *connection,
06204 dbus_uint32_t *in_messages,
06205 dbus_uint32_t *in_bytes,
06206 dbus_uint32_t *in_fds,
06207 dbus_uint32_t *in_peak_bytes,
06208 dbus_uint32_t *in_peak_fds,
06209 dbus_uint32_t *out_messages,
06210 dbus_uint32_t *out_bytes,
06211 dbus_uint32_t *out_fds,
06212 dbus_uint32_t *out_peak_bytes,
06213 dbus_uint32_t *out_peak_fds)
06214 {
06215 CONNECTION_LOCK (connection);
06216
06217 if (in_messages != NULL)
06218 *in_messages = connection->n_incoming;
06219
06220 _dbus_transport_get_stats (connection->transport,
06221 in_bytes, in_fds, in_peak_bytes, in_peak_fds);
06222
06223 if (out_messages != NULL)
06224 *out_messages = connection->n_outgoing;
06225
06226 if (out_bytes != NULL)
06227 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
06228
06229 if (out_fds != NULL)
06230 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06231
06232 if (out_peak_bytes != NULL)
06233 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
06234
06235 if (out_peak_fds != NULL)
06236 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
06237
06238 CONNECTION_UNLOCK (connection);
06239 }
06240 #endif
06241
06249 long
06250 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06251 {
06252 long res;
06253
06254 _dbus_return_val_if_fail (connection != NULL, 0);
06255
06256 CONNECTION_LOCK (connection);
06257 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06258 CONNECTION_UNLOCK (connection);
06259 return res;
06260 }
06261
06262 #ifdef DBUS_BUILD_TESTS
06263
06269 const char*
06270 _dbus_connection_get_address (DBusConnection *connection)
06271 {
06272 return _dbus_transport_get_address (connection->transport);
06273 }
06274 #endif
06275