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-pending-call.h"
00042 #include "dbus-object-tree.h"
00043 #include "dbus-threads-internal.h"
00044 #include "dbus-bus.h"
00045 #include "dbus-marshal-basic.h"
00046
00047 #ifdef DBUS_DISABLE_CHECKS
00048 #define TOOK_LOCK_CHECK(connection)
00049 #define RELEASING_LOCK_CHECK(connection)
00050 #define HAVE_LOCK_CHECK(connection)
00051 #else
00052 #define TOOK_LOCK_CHECK(connection) do { \
00053 _dbus_assert (!(connection)->have_connection_lock); \
00054 (connection)->have_connection_lock = TRUE; \
00055 } while (0)
00056 #define RELEASING_LOCK_CHECK(connection) do { \
00057 _dbus_assert ((connection)->have_connection_lock); \
00058 (connection)->have_connection_lock = FALSE; \
00059 } while (0)
00060 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00061
00062 #endif
00063
00064 #define TRACE_LOCKS 1
00065
00066 #define CONNECTION_LOCK(connection) do { \
00067 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
00068 _dbus_mutex_lock ((connection)->mutex); \
00069 TOOK_LOCK_CHECK (connection); \
00070 } while (0)
00071
00072 #define CONNECTION_UNLOCK(connection) do { \
00073 if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n"); } \
00074 RELEASING_LOCK_CHECK (connection); \
00075 _dbus_mutex_unlock ((connection)->mutex); \
00076 } while (0)
00077
00078 #define SLOTS_LOCK(connection) do { \
00079 _dbus_mutex_lock ((connection)->slot_mutex); \
00080 } while (0)
00081
00082 #define SLOTS_UNLOCK(connection) do { \
00083 _dbus_mutex_unlock ((connection)->slot_mutex); \
00084 } while (0)
00085
00086 #define DISPATCH_STATUS_NAME(s) \
00087 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00088 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00089 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00090 "???")
00091
00212 typedef struct DBusMessageFilter DBusMessageFilter;
00213
00217 struct DBusMessageFilter
00218 {
00219 DBusAtomic refcount;
00220 DBusHandleMessageFunction function;
00221 void *user_data;
00222 DBusFreeFunction free_user_data_function;
00223 };
00224
00225
00229 struct DBusPreallocatedSend
00230 {
00231 DBusConnection *connection;
00232 DBusList *queue_link;
00233 DBusList *counter_link;
00234 };
00235
00236 #ifdef HAVE_DECL_MSG_NOSIGNAL
00237 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00238 #else
00239 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00240 #endif
00241
00245 struct DBusConnection
00246 {
00247 DBusAtomic refcount;
00249 DBusMutex *mutex;
00251 DBusMutex *dispatch_mutex;
00252 DBusCondVar *dispatch_cond;
00253 DBusMutex *io_path_mutex;
00254 DBusCondVar *io_path_cond;
00256 DBusList *outgoing_messages;
00257 DBusList *incoming_messages;
00259 DBusMessage *message_borrowed;
00263 int n_outgoing;
00264 int n_incoming;
00266 DBusCounter *outgoing_counter;
00268 DBusTransport *transport;
00269 DBusWatchList *watches;
00270 DBusTimeoutList *timeouts;
00272 DBusList *filter_list;
00274 DBusMutex *slot_mutex;
00275 DBusDataSlotList slot_list;
00277 DBusHashTable *pending_replies;
00279 dbus_uint32_t client_serial;
00280 DBusList *disconnect_message_link;
00282 DBusWakeupMainFunction wakeup_main_function;
00283 void *wakeup_main_data;
00284 DBusFreeFunction free_wakeup_main_data;
00286 DBusDispatchStatusFunction dispatch_status_function;
00287 void *dispatch_status_data;
00288 DBusFreeFunction free_dispatch_status_data;
00290 DBusDispatchStatus last_dispatch_status;
00292 DBusList *link_cache;
00295 DBusObjectTree *objects;
00297 char *server_guid;
00299
00300
00301
00302
00303 dbus_bool_t dispatch_acquired;
00304 dbus_bool_t io_path_acquired;
00306 unsigned int shareable : 1;
00308 unsigned int exit_on_disconnect : 1;
00310 unsigned int route_peer_messages : 1;
00312 unsigned int disconnected_message_arrived : 1;
00316 unsigned int disconnected_message_processed : 1;
00320 #ifndef DBUS_DISABLE_CHECKS
00321 unsigned int have_connection_lock : 1;
00322 #endif
00323
00324 #ifndef DBUS_DISABLE_CHECKS
00325 int generation;
00326 #endif
00327 };
00328
00329 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00330 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00331 DBusDispatchStatus new_status);
00332 static void _dbus_connection_last_unref (DBusConnection *connection);
00333 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00334 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00335 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00336 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
00337 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
00338 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
00339 dbus_uint32_t client_serial);
00340
00341 static DBusMessageFilter *
00342 _dbus_message_filter_ref (DBusMessageFilter *filter)
00343 {
00344 _dbus_assert (filter->refcount.value > 0);
00345 _dbus_atomic_inc (&filter->refcount);
00346
00347 return filter;
00348 }
00349
00350 static void
00351 _dbus_message_filter_unref (DBusMessageFilter *filter)
00352 {
00353 _dbus_assert (filter->refcount.value > 0);
00354
00355 if (_dbus_atomic_dec (&filter->refcount) == 1)
00356 {
00357 if (filter->free_user_data_function)
00358 (* filter->free_user_data_function) (filter->user_data);
00359
00360 dbus_free (filter);
00361 }
00362 }
00363
00369 void
00370 _dbus_connection_lock (DBusConnection *connection)
00371 {
00372 CONNECTION_LOCK (connection);
00373 }
00374
00380 void
00381 _dbus_connection_unlock (DBusConnection *connection)
00382 {
00383 CONNECTION_UNLOCK (connection);
00384 }
00385
00393 static void
00394 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00395 {
00396 if (connection->wakeup_main_function)
00397 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00398 }
00399
00400 #ifdef DBUS_BUILD_TESTS
00401
00411 dbus_bool_t
00412 _dbus_connection_queue_received_message (DBusConnection *connection,
00413 DBusMessage *message)
00414 {
00415 DBusList *link;
00416
00417 link = _dbus_list_alloc_link (message);
00418 if (link == NULL)
00419 return FALSE;
00420
00421 dbus_message_ref (message);
00422 _dbus_connection_queue_received_message_link (connection, link);
00423
00424 return TRUE;
00425 }
00426
00439 void
00440 _dbus_connection_test_get_locks (DBusConnection *connection,
00441 DBusMutex **mutex_loc,
00442 DBusMutex **dispatch_mutex_loc,
00443 DBusMutex **io_path_mutex_loc,
00444 DBusCondVar **dispatch_cond_loc,
00445 DBusCondVar **io_path_cond_loc)
00446 {
00447 *mutex_loc = connection->mutex;
00448 *dispatch_mutex_loc = connection->dispatch_mutex;
00449 *io_path_mutex_loc = connection->io_path_mutex;
00450 *dispatch_cond_loc = connection->dispatch_cond;
00451 *io_path_cond_loc = connection->io_path_cond;
00452 }
00453 #endif
00454
00463 void
00464 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00465 DBusList *link)
00466 {
00467 DBusPendingCall *pending;
00468 dbus_uint32_t reply_serial;
00469 DBusMessage *message;
00470
00471 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00472
00473 _dbus_list_append_link (&connection->incoming_messages,
00474 link);
00475 message = link->data;
00476
00477
00478 reply_serial = dbus_message_get_reply_serial (message);
00479 if (reply_serial != 0)
00480 {
00481 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00482 reply_serial);
00483 if (pending != NULL)
00484 {
00485 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00486 _dbus_connection_remove_timeout_unlocked (connection,
00487 _dbus_pending_call_get_timeout_unlocked (pending));
00488
00489 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00490 }
00491 }
00492
00493
00494
00495 connection->n_incoming += 1;
00496
00497 _dbus_connection_wakeup_mainloop (connection);
00498
00499 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00500 message,
00501 dbus_message_type_to_string (dbus_message_get_type (message)),
00502 dbus_message_get_path (message) ?
00503 dbus_message_get_path (message) :
00504 "no path",
00505 dbus_message_get_interface (message) ?
00506 dbus_message_get_interface (message) :
00507 "no interface",
00508 dbus_message_get_member (message) ?
00509 dbus_message_get_member (message) :
00510 "no member",
00511 dbus_message_get_signature (message),
00512 dbus_message_get_reply_serial (message),
00513 connection,
00514 connection->n_incoming);}
00515
00524 void
00525 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00526 DBusList *link)
00527 {
00528 HAVE_LOCK_CHECK (connection);
00529
00530 _dbus_list_append_link (&connection->incoming_messages, link);
00531
00532 connection->n_incoming += 1;
00533
00534 _dbus_connection_wakeup_mainloop (connection);
00535
00536 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00537 link->data, connection, connection->n_incoming);
00538 }
00539
00540
00548 dbus_bool_t
00549 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00550 {
00551 HAVE_LOCK_CHECK (connection);
00552 return connection->outgoing_messages != NULL;
00553 }
00554
00564 dbus_bool_t
00565 dbus_connection_has_messages_to_send (DBusConnection *connection)
00566 {
00567 dbus_bool_t v;
00568
00569 _dbus_return_val_if_fail (connection != NULL, FALSE);
00570
00571 CONNECTION_LOCK (connection);
00572 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00573 CONNECTION_UNLOCK (connection);
00574
00575 return v;
00576 }
00577
00585 DBusMessage*
00586 _dbus_connection_get_message_to_send (DBusConnection *connection)
00587 {
00588 HAVE_LOCK_CHECK (connection);
00589
00590 return _dbus_list_get_last (&connection->outgoing_messages);
00591 }
00592
00601 void
00602 _dbus_connection_message_sent (DBusConnection *connection,
00603 DBusMessage *message)
00604 {
00605 DBusList *link;
00606
00607 HAVE_LOCK_CHECK (connection);
00608
00609
00610
00611
00612
00613
00614 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00615 _dbus_assert (link != NULL);
00616 _dbus_assert (link->data == message);
00617
00618
00619 _dbus_list_unlink (&connection->outgoing_messages,
00620 link);
00621 _dbus_list_prepend_link (&connection->link_cache, link);
00622
00623 connection->n_outgoing -= 1;
00624
00625 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00626 message,
00627 dbus_message_type_to_string (dbus_message_get_type (message)),
00628 dbus_message_get_path (message) ?
00629 dbus_message_get_path (message) :
00630 "no path",
00631 dbus_message_get_interface (message) ?
00632 dbus_message_get_interface (message) :
00633 "no interface",
00634 dbus_message_get_member (message) ?
00635 dbus_message_get_member (message) :
00636 "no member",
00637 dbus_message_get_signature (message),
00638 connection, connection->n_outgoing);
00639
00640
00641 _dbus_message_remove_counter (message, connection->outgoing_counter,
00642 &link);
00643 _dbus_list_prepend_link (&connection->link_cache, link);
00644
00645 dbus_message_unref (message);
00646 }
00647
00649 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00650 DBusWatch *watch);
00652 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00653 DBusWatch *watch);
00655 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00656 DBusWatch *watch,
00657 dbus_bool_t enabled);
00658
00659 static dbus_bool_t
00660 protected_change_watch (DBusConnection *connection,
00661 DBusWatch *watch,
00662 DBusWatchAddFunction add_function,
00663 DBusWatchRemoveFunction remove_function,
00664 DBusWatchToggleFunction toggle_function,
00665 dbus_bool_t enabled)
00666 {
00667 dbus_bool_t retval;
00668
00669 HAVE_LOCK_CHECK (connection);
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 if (connection->watches)
00690 {
00691 if (add_function)
00692 retval = (* add_function) (connection->watches, watch);
00693 else if (remove_function)
00694 {
00695 retval = TRUE;
00696 (* remove_function) (connection->watches, watch);
00697 }
00698 else
00699 {
00700 retval = TRUE;
00701 (* toggle_function) (connection->watches, watch, enabled);
00702 }
00703 return retval;
00704 }
00705 else
00706 return FALSE;
00707 }
00708
00709
00721 dbus_bool_t
00722 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00723 DBusWatch *watch)
00724 {
00725 return protected_change_watch (connection, watch,
00726 _dbus_watch_list_add_watch,
00727 NULL, NULL, FALSE);
00728 }
00729
00739 void
00740 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00741 DBusWatch *watch)
00742 {
00743 protected_change_watch (connection, watch,
00744 NULL,
00745 _dbus_watch_list_remove_watch,
00746 NULL, FALSE);
00747 }
00748
00759 void
00760 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00761 DBusWatch *watch,
00762 dbus_bool_t enabled)
00763 {
00764 _dbus_assert (watch != NULL);
00765
00766 protected_change_watch (connection, watch,
00767 NULL, NULL,
00768 _dbus_watch_list_toggle_watch,
00769 enabled);
00770 }
00771
00773 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00774 DBusTimeout *timeout);
00776 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00777 DBusTimeout *timeout);
00779 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00780 DBusTimeout *timeout,
00781 dbus_bool_t enabled);
00782
00783 static dbus_bool_t
00784 protected_change_timeout (DBusConnection *connection,
00785 DBusTimeout *timeout,
00786 DBusTimeoutAddFunction add_function,
00787 DBusTimeoutRemoveFunction remove_function,
00788 DBusTimeoutToggleFunction toggle_function,
00789 dbus_bool_t enabled)
00790 {
00791 dbus_bool_t retval;
00792
00793 HAVE_LOCK_CHECK (connection);
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 if (connection->timeouts)
00814 {
00815 if (add_function)
00816 retval = (* add_function) (connection->timeouts, timeout);
00817 else if (remove_function)
00818 {
00819 retval = TRUE;
00820 (* remove_function) (connection->timeouts, timeout);
00821 }
00822 else
00823 {
00824 retval = TRUE;
00825 (* toggle_function) (connection->timeouts, timeout, enabled);
00826 }
00827 return retval;
00828 }
00829 else
00830 return FALSE;
00831 }
00832
00845 dbus_bool_t
00846 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00847 DBusTimeout *timeout)
00848 {
00849 return protected_change_timeout (connection, timeout,
00850 _dbus_timeout_list_add_timeout,
00851 NULL, NULL, FALSE);
00852 }
00853
00863 void
00864 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00865 DBusTimeout *timeout)
00866 {
00867 protected_change_timeout (connection, timeout,
00868 NULL,
00869 _dbus_timeout_list_remove_timeout,
00870 NULL, FALSE);
00871 }
00872
00883 void
00884 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00885 DBusTimeout *timeout,
00886 dbus_bool_t enabled)
00887 {
00888 protected_change_timeout (connection, timeout,
00889 NULL, NULL,
00890 _dbus_timeout_list_toggle_timeout,
00891 enabled);
00892 }
00893
00894 static dbus_bool_t
00895 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00896 DBusPendingCall *pending)
00897 {
00898 dbus_uint32_t reply_serial;
00899 DBusTimeout *timeout;
00900
00901 HAVE_LOCK_CHECK (connection);
00902
00903 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00904
00905 _dbus_assert (reply_serial != 0);
00906
00907 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00908
00909 if (timeout)
00910 {
00911 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00912 return FALSE;
00913
00914 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00915 reply_serial,
00916 pending))
00917 {
00918 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00919
00920 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00921 HAVE_LOCK_CHECK (connection);
00922 return FALSE;
00923 }
00924
00925 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00926 }
00927 else
00928 {
00929 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00930 reply_serial,
00931 pending))
00932 {
00933 HAVE_LOCK_CHECK (connection);
00934 return FALSE;
00935 }
00936 }
00937
00938 _dbus_pending_call_ref_unlocked (pending);
00939
00940 HAVE_LOCK_CHECK (connection);
00941
00942 return TRUE;
00943 }
00944
00945 static void
00946 free_pending_call_on_hash_removal (void *data)
00947 {
00948 DBusPendingCall *pending;
00949 DBusConnection *connection;
00950
00951 if (data == NULL)
00952 return;
00953
00954 pending = data;
00955
00956 connection = _dbus_pending_call_get_connection_unlocked (pending);
00957
00958 HAVE_LOCK_CHECK (connection);
00959
00960 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00961 {
00962 _dbus_connection_remove_timeout_unlocked (connection,
00963 _dbus_pending_call_get_timeout_unlocked (pending));
00964
00965 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00966 }
00967
00968
00969
00970
00971
00972
00973 _dbus_connection_ref_unlocked (connection);
00974 _dbus_pending_call_unref_and_unlock (pending);
00975 CONNECTION_LOCK (connection);
00976 _dbus_connection_unref_unlocked (connection);
00977 }
00978
00979 static void
00980 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00981 DBusPendingCall *pending)
00982 {
00983
00984
00985
00986 _dbus_hash_table_remove_int (connection->pending_replies,
00987 _dbus_pending_call_get_reply_serial_unlocked (pending));
00988 }
00989
00990 static void
00991 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00992 DBusPendingCall *pending)
00993 {
00994
00995
00996
00997
00998
00999
01000
01001 _dbus_pending_call_ref_unlocked (pending);
01002 _dbus_hash_table_remove_int (connection->pending_replies,
01003 _dbus_pending_call_get_reply_serial_unlocked (pending));
01004
01005 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01006 _dbus_connection_remove_timeout_unlocked (connection,
01007 _dbus_pending_call_get_timeout_unlocked (pending));
01008
01009 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01010
01011 _dbus_pending_call_unref_and_unlock (pending);
01012 }
01013
01022 void
01023 _dbus_connection_remove_pending_call (DBusConnection *connection,
01024 DBusPendingCall *pending)
01025 {
01026 CONNECTION_LOCK (connection);
01027 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01028 }
01029
01039 static dbus_bool_t
01040 _dbus_connection_acquire_io_path (DBusConnection *connection,
01041 int timeout_milliseconds)
01042 {
01043 dbus_bool_t we_acquired;
01044
01045 HAVE_LOCK_CHECK (connection);
01046
01047
01048 _dbus_connection_ref_unlocked (connection);
01049
01050
01051 CONNECTION_UNLOCK (connection);
01052
01053 _dbus_verbose ("locking io_path_mutex\n");
01054 _dbus_mutex_lock (connection->io_path_mutex);
01055
01056 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01057 connection->io_path_acquired, timeout_milliseconds);
01058
01059 we_acquired = FALSE;
01060
01061 if (connection->io_path_acquired)
01062 {
01063 if (timeout_milliseconds != -1)
01064 {
01065 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01066 timeout_milliseconds);
01067
01068 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01069 connection->io_path_mutex,
01070 timeout_milliseconds))
01071 {
01072
01073
01074
01075
01076
01077
01078
01079
01080 }
01081 }
01082 else
01083 {
01084 while (connection->io_path_acquired)
01085 {
01086 _dbus_verbose ("waiting for IO path to be acquirable\n");
01087 _dbus_condvar_wait (connection->io_path_cond,
01088 connection->io_path_mutex);
01089 }
01090 }
01091 }
01092
01093 if (!connection->io_path_acquired)
01094 {
01095 we_acquired = TRUE;
01096 connection->io_path_acquired = TRUE;
01097 }
01098
01099 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01100 connection->io_path_acquired, we_acquired);
01101
01102 _dbus_verbose ("unlocking io_path_mutex\n");
01103 _dbus_mutex_unlock (connection->io_path_mutex);
01104
01105 CONNECTION_LOCK (connection);
01106
01107 HAVE_LOCK_CHECK (connection);
01108
01109 _dbus_connection_unref_unlocked (connection);
01110
01111 return we_acquired;
01112 }
01113
01121 static void
01122 _dbus_connection_release_io_path (DBusConnection *connection)
01123 {
01124 HAVE_LOCK_CHECK (connection);
01125
01126 _dbus_verbose ("locking io_path_mutex\n");
01127 _dbus_mutex_lock (connection->io_path_mutex);
01128
01129 _dbus_assert (connection->io_path_acquired);
01130
01131 _dbus_verbose ("start connection->io_path_acquired = %d\n",
01132 connection->io_path_acquired);
01133
01134 connection->io_path_acquired = FALSE;
01135 _dbus_condvar_wake_one (connection->io_path_cond);
01136
01137 _dbus_verbose ("unlocking io_path_mutex\n");
01138 _dbus_mutex_unlock (connection->io_path_mutex);
01139 }
01140
01176 void
01177 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01178 DBusPendingCall *pending,
01179 unsigned int flags,
01180 int timeout_milliseconds)
01181 {
01182 _dbus_verbose ("start\n");
01183
01184 HAVE_LOCK_CHECK (connection);
01185
01186 if (connection->n_outgoing == 0)
01187 flags &= ~DBUS_ITERATION_DO_WRITING;
01188
01189 if (_dbus_connection_acquire_io_path (connection,
01190 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01191 {
01192 HAVE_LOCK_CHECK (connection);
01193
01194 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01195 {
01196 _dbus_verbose ("pending call completed while acquiring I/O path");
01197 }
01198 else if ( (pending != NULL) &&
01199 _dbus_connection_peek_for_reply_unlocked (connection,
01200 _dbus_pending_call_get_reply_serial_unlocked (pending)))
01201 {
01202 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01203 }
01204 else
01205 {
01206 _dbus_transport_do_iteration (connection->transport,
01207 flags, timeout_milliseconds);
01208 }
01209
01210 _dbus_connection_release_io_path (connection);
01211 }
01212
01213 HAVE_LOCK_CHECK (connection);
01214
01215 _dbus_verbose ("end\n");
01216 }
01217
01227 DBusConnection*
01228 _dbus_connection_new_for_transport (DBusTransport *transport)
01229 {
01230 DBusConnection *connection;
01231 DBusWatchList *watch_list;
01232 DBusTimeoutList *timeout_list;
01233 DBusHashTable *pending_replies;
01234 DBusList *disconnect_link;
01235 DBusMessage *disconnect_message;
01236 DBusCounter *outgoing_counter;
01237 DBusObjectTree *objects;
01238
01239 watch_list = NULL;
01240 connection = NULL;
01241 pending_replies = NULL;
01242 timeout_list = NULL;
01243 disconnect_link = NULL;
01244 disconnect_message = NULL;
01245 outgoing_counter = NULL;
01246 objects = NULL;
01247
01248 watch_list = _dbus_watch_list_new ();
01249 if (watch_list == NULL)
01250 goto error;
01251
01252 timeout_list = _dbus_timeout_list_new ();
01253 if (timeout_list == NULL)
01254 goto error;
01255
01256 pending_replies =
01257 _dbus_hash_table_new (DBUS_HASH_INT,
01258 NULL,
01259 (DBusFreeFunction)free_pending_call_on_hash_removal);
01260 if (pending_replies == NULL)
01261 goto error;
01262
01263 connection = dbus_new0 (DBusConnection, 1);
01264 if (connection == NULL)
01265 goto error;
01266
01267 _dbus_mutex_new_at_location (&connection->mutex);
01268 if (connection->mutex == NULL)
01269 goto error;
01270
01271 _dbus_mutex_new_at_location (&connection->io_path_mutex);
01272 if (connection->io_path_mutex == NULL)
01273 goto error;
01274
01275 _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01276 if (connection->dispatch_mutex == NULL)
01277 goto error;
01278
01279 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01280 if (connection->dispatch_cond == NULL)
01281 goto error;
01282
01283 _dbus_condvar_new_at_location (&connection->io_path_cond);
01284 if (connection->io_path_cond == NULL)
01285 goto error;
01286
01287 _dbus_mutex_new_at_location (&connection->slot_mutex);
01288 if (connection->slot_mutex == NULL)
01289 goto error;
01290
01291 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01292 DBUS_INTERFACE_LOCAL,
01293 "Disconnected");
01294
01295 if (disconnect_message == NULL)
01296 goto error;
01297
01298 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01299 if (disconnect_link == NULL)
01300 goto error;
01301
01302 outgoing_counter = _dbus_counter_new ();
01303 if (outgoing_counter == NULL)
01304 goto error;
01305
01306 objects = _dbus_object_tree_new (connection);
01307 if (objects == NULL)
01308 goto error;
01309
01310 if (_dbus_modify_sigpipe)
01311 _dbus_disable_sigpipe ();
01312
01313 connection->refcount.value = 1;
01314 connection->transport = transport;
01315 connection->watches = watch_list;
01316 connection->timeouts = timeout_list;
01317 connection->pending_replies = pending_replies;
01318 connection->outgoing_counter = outgoing_counter;
01319 connection->filter_list = NULL;
01320 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01321 connection->objects = objects;
01322 connection->exit_on_disconnect = FALSE;
01323 connection->shareable = FALSE;
01324 connection->route_peer_messages = FALSE;
01325 connection->disconnected_message_arrived = FALSE;
01326 connection->disconnected_message_processed = FALSE;
01327
01328 #ifndef DBUS_DISABLE_CHECKS
01329 connection->generation = _dbus_current_generation;
01330 #endif
01331
01332 _dbus_data_slot_list_init (&connection->slot_list);
01333
01334 connection->client_serial = 1;
01335
01336 connection->disconnect_message_link = disconnect_link;
01337
01338 CONNECTION_LOCK (connection);
01339
01340 if (!_dbus_transport_set_connection (transport, connection))
01341 {
01342 CONNECTION_UNLOCK (connection);
01343
01344 goto error;
01345 }
01346
01347 _dbus_transport_ref (transport);
01348
01349 CONNECTION_UNLOCK (connection);
01350
01351 return connection;
01352
01353 error:
01354 if (disconnect_message != NULL)
01355 dbus_message_unref (disconnect_message);
01356
01357 if (disconnect_link != NULL)
01358 _dbus_list_free_link (disconnect_link);
01359
01360 if (connection != NULL)
01361 {
01362 _dbus_condvar_free_at_location (&connection->io_path_cond);
01363 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01364 _dbus_mutex_free_at_location (&connection->mutex);
01365 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01366 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01367 _dbus_mutex_free_at_location (&connection->slot_mutex);
01368 dbus_free (connection);
01369 }
01370 if (pending_replies)
01371 _dbus_hash_table_unref (pending_replies);
01372
01373 if (watch_list)
01374 _dbus_watch_list_free (watch_list);
01375
01376 if (timeout_list)
01377 _dbus_timeout_list_free (timeout_list);
01378
01379 if (outgoing_counter)
01380 _dbus_counter_unref (outgoing_counter);
01381
01382 if (objects)
01383 _dbus_object_tree_unref (objects);
01384
01385 return NULL;
01386 }
01387
01395 DBusConnection *
01396 _dbus_connection_ref_unlocked (DBusConnection *connection)
01397 {
01398 _dbus_assert (connection != NULL);
01399 _dbus_assert (connection->generation == _dbus_current_generation);
01400
01401 HAVE_LOCK_CHECK (connection);
01402
01403 #ifdef DBUS_HAVE_ATOMIC_INT
01404 _dbus_atomic_inc (&connection->refcount);
01405 #else
01406 _dbus_assert (connection->refcount.value > 0);
01407 connection->refcount.value += 1;
01408 #endif
01409
01410 return connection;
01411 }
01412
01419 void
01420 _dbus_connection_unref_unlocked (DBusConnection *connection)
01421 {
01422 dbus_bool_t last_unref;
01423
01424 HAVE_LOCK_CHECK (connection);
01425
01426 _dbus_assert (connection != NULL);
01427
01428
01429
01430
01431
01432 #ifdef DBUS_HAVE_ATOMIC_INT
01433 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01434 #else
01435 _dbus_assert (connection->refcount.value > 0);
01436
01437 connection->refcount.value -= 1;
01438 last_unref = (connection->refcount.value == 0);
01439 #if 0
01440 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01441 #endif
01442 #endif
01443
01444 if (last_unref)
01445 _dbus_connection_last_unref (connection);
01446 }
01447
01448 static dbus_uint32_t
01449 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01450 {
01451 dbus_uint32_t serial;
01452
01453 serial = connection->client_serial++;
01454
01455 if (connection->client_serial == 0)
01456 connection->client_serial = 1;
01457
01458 return serial;
01459 }
01460
01474 dbus_bool_t
01475 _dbus_connection_handle_watch (DBusWatch *watch,
01476 unsigned int condition,
01477 void *data)
01478 {
01479 DBusConnection *connection;
01480 dbus_bool_t retval;
01481 DBusDispatchStatus status;
01482
01483 connection = data;
01484
01485 _dbus_verbose ("start\n");
01486
01487 CONNECTION_LOCK (connection);
01488
01489 if (!_dbus_connection_acquire_io_path (connection, 1))
01490 {
01491
01492 CONNECTION_UNLOCK (connection);
01493 return TRUE;
01494 }
01495
01496 HAVE_LOCK_CHECK (connection);
01497 retval = _dbus_transport_handle_watch (connection->transport,
01498 watch, condition);
01499
01500 _dbus_connection_release_io_path (connection);
01501
01502 HAVE_LOCK_CHECK (connection);
01503
01504 _dbus_verbose ("middle\n");
01505
01506 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01507
01508
01509 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01510
01511 _dbus_verbose ("end\n");
01512
01513 return retval;
01514 }
01515
01516 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01517 static DBusHashTable *shared_connections = NULL;
01518 static DBusList *shared_connections_no_guid = NULL;
01519
01520 static void
01521 close_connection_on_shutdown (DBusConnection *connection)
01522 {
01523 DBusMessage *message;
01524
01525 dbus_connection_ref (connection);
01526 _dbus_connection_close_possibly_shared (connection);
01527
01528
01529 while ((message = dbus_connection_pop_message (connection)))
01530 {
01531 dbus_message_unref (message);
01532 }
01533 dbus_connection_unref (connection);
01534 }
01535
01536 static void
01537 shared_connections_shutdown (void *data)
01538 {
01539 int n_entries;
01540
01541 _DBUS_LOCK (shared_connections);
01542
01543
01544 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01545 {
01546 DBusConnection *connection;
01547 DBusHashIter iter;
01548
01549 _dbus_hash_iter_init (shared_connections, &iter);
01550 _dbus_hash_iter_next (&iter);
01551
01552 connection = _dbus_hash_iter_get_value (&iter);
01553
01554 _DBUS_UNLOCK (shared_connections);
01555 close_connection_on_shutdown (connection);
01556 _DBUS_LOCK (shared_connections);
01557
01558
01559 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01560 }
01561
01562 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01563
01564 _dbus_hash_table_unref (shared_connections);
01565 shared_connections = NULL;
01566
01567 if (shared_connections_no_guid != NULL)
01568 {
01569 DBusConnection *connection;
01570 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01571 while (connection != NULL)
01572 {
01573 _DBUS_UNLOCK (shared_connections);
01574 close_connection_on_shutdown (connection);
01575 _DBUS_LOCK (shared_connections);
01576 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01577 }
01578 }
01579
01580 shared_connections_no_guid = NULL;
01581
01582 _DBUS_UNLOCK (shared_connections);
01583 }
01584
01585 static dbus_bool_t
01586 connection_lookup_shared (DBusAddressEntry *entry,
01587 DBusConnection **result)
01588 {
01589 _dbus_verbose ("checking for existing connection\n");
01590
01591 *result = NULL;
01592
01593 _DBUS_LOCK (shared_connections);
01594
01595 if (shared_connections == NULL)
01596 {
01597 _dbus_verbose ("creating shared_connections hash table\n");
01598
01599 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01600 dbus_free,
01601 NULL);
01602 if (shared_connections == NULL)
01603 {
01604 _DBUS_UNLOCK (shared_connections);
01605 return FALSE;
01606 }
01607
01608 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01609 {
01610 _dbus_hash_table_unref (shared_connections);
01611 shared_connections = NULL;
01612 _DBUS_UNLOCK (shared_connections);
01613 return FALSE;
01614 }
01615
01616 _dbus_verbose (" successfully created shared_connections\n");
01617
01618 _DBUS_UNLOCK (shared_connections);
01619 return TRUE;
01620 }
01621 else
01622 {
01623 const char *guid;
01624
01625 guid = dbus_address_entry_get_value (entry, "guid");
01626
01627 if (guid != NULL)
01628 {
01629 DBusConnection *connection;
01630
01631 connection = _dbus_hash_table_lookup_string (shared_connections,
01632 guid);
01633
01634 if (connection)
01635 {
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650 CONNECTION_LOCK (connection);
01651 if (_dbus_connection_get_is_connected_unlocked (connection))
01652 {
01653 _dbus_connection_ref_unlocked (connection);
01654 *result = connection;
01655 _dbus_verbose ("looked up existing connection to server guid %s\n",
01656 guid);
01657 }
01658 else
01659 {
01660 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01661 guid);
01662 }
01663 CONNECTION_UNLOCK (connection);
01664 }
01665 }
01666
01667 _DBUS_UNLOCK (shared_connections);
01668 return TRUE;
01669 }
01670 }
01671
01672 static dbus_bool_t
01673 connection_record_shared_unlocked (DBusConnection *connection,
01674 const char *guid)
01675 {
01676 char *guid_key;
01677 char *guid_in_connection;
01678
01679 HAVE_LOCK_CHECK (connection);
01680 _dbus_assert (connection->server_guid == NULL);
01681 _dbus_assert (connection->shareable);
01682
01683
01684
01685
01686
01687 _dbus_connection_ref_unlocked (connection);
01688
01689 if (guid == NULL)
01690 {
01691 _DBUS_LOCK (shared_connections);
01692
01693 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01694 {
01695 _DBUS_UNLOCK (shared_connections);
01696 return FALSE;
01697 }
01698
01699 _DBUS_UNLOCK (shared_connections);
01700 return TRUE;
01701 }
01702
01703
01704
01705
01706
01707
01708 guid_key = _dbus_strdup (guid);
01709 if (guid_key == NULL)
01710 return FALSE;
01711
01712 guid_in_connection = _dbus_strdup (guid);
01713 if (guid_in_connection == NULL)
01714 {
01715 dbus_free (guid_key);
01716 return FALSE;
01717 }
01718
01719 _DBUS_LOCK (shared_connections);
01720 _dbus_assert (shared_connections != NULL);
01721
01722 if (!_dbus_hash_table_insert_string (shared_connections,
01723 guid_key, connection))
01724 {
01725 dbus_free (guid_key);
01726 dbus_free (guid_in_connection);
01727 _DBUS_UNLOCK (shared_connections);
01728 return FALSE;
01729 }
01730
01731 connection->server_guid = guid_in_connection;
01732
01733 _dbus_verbose ("stored connection to %s to be shared\n",
01734 connection->server_guid);
01735
01736 _DBUS_UNLOCK (shared_connections);
01737
01738 _dbus_assert (connection->server_guid != NULL);
01739
01740 return TRUE;
01741 }
01742
01743 static void
01744 connection_forget_shared_unlocked (DBusConnection *connection)
01745 {
01746 HAVE_LOCK_CHECK (connection);
01747
01748 if (!connection->shareable)
01749 return;
01750
01751 _DBUS_LOCK (shared_connections);
01752
01753 if (connection->server_guid != NULL)
01754 {
01755 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01756 connection->server_guid);
01757
01758 if (!_dbus_hash_table_remove_string (shared_connections,
01759 connection->server_guid))
01760 _dbus_assert_not_reached ("connection was not in the shared table");
01761
01762 dbus_free (connection->server_guid);
01763 connection->server_guid = NULL;
01764 }
01765 else
01766 {
01767 _dbus_list_remove (&shared_connections_no_guid, connection);
01768 }
01769
01770 _DBUS_UNLOCK (shared_connections);
01771
01772
01773 _dbus_connection_unref_unlocked (connection);
01774 }
01775
01776 static DBusConnection*
01777 connection_try_from_address_entry (DBusAddressEntry *entry,
01778 DBusError *error)
01779 {
01780 DBusTransport *transport;
01781 DBusConnection *connection;
01782
01783 transport = _dbus_transport_open (entry, error);
01784
01785 if (transport == NULL)
01786 {
01787 _DBUS_ASSERT_ERROR_IS_SET (error);
01788 return NULL;
01789 }
01790
01791 connection = _dbus_connection_new_for_transport (transport);
01792
01793 _dbus_transport_unref (transport);
01794
01795 if (connection == NULL)
01796 {
01797 _DBUS_SET_OOM (error);
01798 return NULL;
01799 }
01800
01801 #ifndef DBUS_DISABLE_CHECKS
01802 _dbus_assert (!connection->have_connection_lock);
01803 #endif
01804 return connection;
01805 }
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819 static DBusConnection*
01820 _dbus_connection_open_internal (const char *address,
01821 dbus_bool_t shared,
01822 DBusError *error)
01823 {
01824 DBusConnection *connection;
01825 DBusAddressEntry **entries;
01826 DBusError tmp_error = DBUS_ERROR_INIT;
01827 DBusError first_error = DBUS_ERROR_INIT;
01828 int len, i;
01829
01830 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01831
01832 _dbus_verbose ("opening %s connection to: %s\n",
01833 shared ? "shared" : "private", address);
01834
01835 if (!dbus_parse_address (address, &entries, &len, error))
01836 return NULL;
01837
01838 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01839
01840 connection = NULL;
01841
01842 for (i = 0; i < len; i++)
01843 {
01844 if (shared)
01845 {
01846 if (!connection_lookup_shared (entries[i], &connection))
01847 _DBUS_SET_OOM (&tmp_error);
01848 }
01849
01850 if (connection == NULL)
01851 {
01852 connection = connection_try_from_address_entry (entries[i],
01853 &tmp_error);
01854
01855 if (connection != NULL && shared)
01856 {
01857 const char *guid;
01858
01859 connection->shareable = TRUE;
01860
01861
01862 guid = dbus_address_entry_get_value (entries[i], "guid");
01863
01864 CONNECTION_LOCK (connection);
01865
01866 if (!connection_record_shared_unlocked (connection, guid))
01867 {
01868 _DBUS_SET_OOM (&tmp_error);
01869 _dbus_connection_close_possibly_shared_and_unlock (connection);
01870 dbus_connection_unref (connection);
01871 connection = NULL;
01872 }
01873 else
01874 CONNECTION_UNLOCK (connection);
01875 }
01876 }
01877
01878 if (connection)
01879 break;
01880
01881 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01882
01883 if (i == 0)
01884 dbus_move_error (&tmp_error, &first_error);
01885 else
01886 dbus_error_free (&tmp_error);
01887 }
01888
01889 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01890 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01891
01892 if (connection == NULL)
01893 {
01894 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01895 dbus_move_error (&first_error, error);
01896 }
01897 else
01898 dbus_error_free (&first_error);
01899
01900 dbus_address_entries_free (entries);
01901 return connection;
01902 }
01903
01912 void
01913 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01914 {
01915 _dbus_assert (connection != NULL);
01916 _dbus_assert (connection->generation == _dbus_current_generation);
01917
01918 CONNECTION_LOCK (connection);
01919 _dbus_connection_close_possibly_shared_and_unlock (connection);
01920 }
01921
01922 static DBusPreallocatedSend*
01923 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01924 {
01925 DBusPreallocatedSend *preallocated;
01926
01927 HAVE_LOCK_CHECK (connection);
01928
01929 _dbus_assert (connection != NULL);
01930
01931 preallocated = dbus_new (DBusPreallocatedSend, 1);
01932 if (preallocated == NULL)
01933 return NULL;
01934
01935 if (connection->link_cache != NULL)
01936 {
01937 preallocated->queue_link =
01938 _dbus_list_pop_first_link (&connection->link_cache);
01939 preallocated->queue_link->data = NULL;
01940 }
01941 else
01942 {
01943 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01944 if (preallocated->queue_link == NULL)
01945 goto failed_0;
01946 }
01947
01948 if (connection->link_cache != NULL)
01949 {
01950 preallocated->counter_link =
01951 _dbus_list_pop_first_link (&connection->link_cache);
01952 preallocated->counter_link->data = connection->outgoing_counter;
01953 }
01954 else
01955 {
01956 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01957 if (preallocated->counter_link == NULL)
01958 goto failed_1;
01959 }
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 _dbus_message_add_counter_link (message,
01989 preallocated->counter_link);
01990
01991 dbus_free (preallocated);
01992 preallocated = NULL;
01993
01994 dbus_message_ref (message);
01995
01996 connection->n_outgoing += 1;
01997
01998 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01999 message,
02000 dbus_message_type_to_string (dbus_message_get_type (message)),
02001 dbus_message_get_path (message) ?
02002 dbus_message_get_path (message) :
02003 "no path",
02004 dbus_message_get_interface (message) ?
02005 dbus_message_get_interface (message) :
02006 "no interface",
02007 dbus_message_get_member (message) ?
02008 dbus_message_get_member (message) :
02009 "no member",
02010 dbus_message_get_signature (message),
02011 dbus_message_get_destination (message) ?
02012 dbus_message_get_destination (message) :
02013 "null",
02014 connection,
02015 connection->n_outgoing);
02016
02017 if (dbus_message_get_serial (message) == 0)
02018 {
02019 serial = _dbus_connection_get_next_client_serial (connection);
02020 dbus_message_set_serial (message, serial);
02021 if (client_serial)
02022 *client_serial = serial;
02023 }
02024 else
02025 {
02026 if (client_serial)
02027 *client_serial = dbus_message_get_serial (message);
02028 }
02029
02030 _dbus_verbose ("Message %p serial is %u\n",
02031 message, dbus_message_get_serial (message));
02032
02033 dbus_message_lock (message);
02034
02035
02036
02037
02038 _dbus_connection_do_iteration_unlocked (connection,
02039 NULL,
02040 DBUS_ITERATION_DO_WRITING,
02041 -1);
02042
02043
02044 if (connection->n_outgoing > 0)
02045 _dbus_connection_wakeup_mainloop (connection);
02046 }
02047
02048 static void
02049 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02050 DBusPreallocatedSend *preallocated,
02051 DBusMessage *message,
02052 dbus_uint32_t *client_serial)
02053 {
02054 DBusDispatchStatus status;
02055
02056 HAVE_LOCK_CHECK (connection);
02057
02058 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02059 preallocated,
02060 message, client_serial);
02061
02062 _dbus_verbose ("middle\n");
02063 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02064
02065
02066 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02067 }
02068
02078 dbus_bool_t
02079 _dbus_connection_send_and_unlock (DBusConnection *connection,
02080 DBusMessage *message,
02081 dbus_uint32_t *client_serial)
02082 {
02083 DBusPreallocatedSend *preallocated;
02084
02085 _dbus_assert (connection != NULL);
02086 _dbus_assert (message != NULL);
02087
02088 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02089 if (preallocated == NULL)
02090 {
02091 CONNECTION_UNLOCK (connection);
02092 return FALSE;
02093 }
02094
02095 _dbus_connection_send_preallocated_and_unlock (connection,
02096 preallocated,
02097 message,
02098 client_serial);
02099 return TRUE;
02100 }
02101
02126 void
02127 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02128 {
02129 CONNECTION_LOCK (connection);
02130
02131 _dbus_assert (connection->refcount.value > 0);
02132
02133 if (connection->refcount.value == 1)
02134 _dbus_connection_close_possibly_shared_and_unlock (connection);
02135 else
02136 CONNECTION_UNLOCK (connection);
02137 }
02138
02139
02149 static void
02150 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02151 {
02152 if (timeout_milliseconds == -1)
02153 _dbus_sleep_milliseconds (1000);
02154 else if (timeout_milliseconds < 100)
02155 ;
02156 else if (timeout_milliseconds <= 1000)
02157 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02158 else
02159 _dbus_sleep_milliseconds (1000);
02160 }
02161
02162 static DBusMessage *
02163 generate_local_error_message (dbus_uint32_t serial,
02164 char *error_name,
02165 char *error_msg)
02166 {
02167 DBusMessage *message;
02168 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02169 if (!message)
02170 goto out;
02171
02172 if (!dbus_message_set_error_name (message, error_name))
02173 {
02174 dbus_message_unref (message);
02175 message = NULL;
02176 goto out;
02177 }
02178
02179 dbus_message_set_no_reply (message, TRUE);
02180
02181 if (!dbus_message_set_reply_serial (message,
02182 serial))
02183 {
02184 dbus_message_unref (message);
02185 message = NULL;
02186 goto out;
02187 }
02188
02189 if (error_msg != NULL)
02190 {
02191 DBusMessageIter iter;
02192
02193 dbus_message_iter_init_append (message, &iter);
02194 if (!dbus_message_iter_append_basic (&iter,
02195 DBUS_TYPE_STRING,
02196 &error_msg))
02197 {
02198 dbus_message_unref (message);
02199 message = NULL;
02200 goto out;
02201 }
02202 }
02203
02204 out:
02205 return message;
02206 }
02207
02208
02209
02210
02211 static dbus_bool_t
02212 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02213 dbus_uint32_t client_serial)
02214 {
02215 DBusList *link;
02216 HAVE_LOCK_CHECK (connection);
02217
02218 link = _dbus_list_get_first_link (&connection->incoming_messages);
02219
02220 while (link != NULL)
02221 {
02222 DBusMessage *reply = link->data;
02223
02224 if (dbus_message_get_reply_serial (reply) == client_serial)
02225 {
02226 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02227 return TRUE;
02228 }
02229 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02230 }
02231
02232 return FALSE;
02233 }
02234
02235
02236
02237
02238 static DBusMessage*
02239 check_for_reply_unlocked (DBusConnection *connection,
02240 dbus_uint32_t client_serial)
02241 {
02242 DBusList *link;
02243
02244 HAVE_LOCK_CHECK (connection);
02245
02246 link = _dbus_list_get_first_link (&connection->incoming_messages);
02247
02248 while (link != NULL)
02249 {
02250 DBusMessage *reply = link->data;
02251
02252 if (dbus_message_get_reply_serial (reply) == client_serial)
02253 {
02254 _dbus_list_remove_link (&connection->incoming_messages, link);
02255 connection->n_incoming -= 1;
02256 return reply;
02257 }
02258 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02259 }
02260
02261 return NULL;
02262 }
02263
02264 static void
02265 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02266 {
02267
02268
02269
02270
02271
02272 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02273 {
02274 DBusPendingCall *pending;
02275 DBusHashIter iter;
02276
02277 _dbus_hash_iter_init (connection->pending_replies, &iter);
02278 _dbus_hash_iter_next (&iter);
02279
02280 pending = _dbus_hash_iter_get_value (&iter);
02281 _dbus_pending_call_ref_unlocked (pending);
02282
02283 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02284 connection);
02285
02286 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02287 _dbus_connection_remove_timeout_unlocked (connection,
02288 _dbus_pending_call_get_timeout_unlocked (pending));
02289 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02290 _dbus_hash_iter_remove_entry (&iter);
02291
02292 _dbus_pending_call_unref_and_unlock (pending);
02293 CONNECTION_LOCK (connection);
02294 }
02295 HAVE_LOCK_CHECK (connection);
02296 }
02297
02298 static void
02299 complete_pending_call_and_unlock (DBusConnection *connection,
02300 DBusPendingCall *pending,
02301 DBusMessage *message)
02302 {
02303 _dbus_pending_call_set_reply_unlocked (pending, message);
02304 _dbus_pending_call_ref_unlocked (pending);
02305 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02306
02307
02308 _dbus_pending_call_complete (pending);
02309 dbus_pending_call_unref (pending);
02310 }
02311
02312 static dbus_bool_t
02313 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02314 DBusPendingCall *pending)
02315 {
02316 DBusMessage *reply;
02317 DBusDispatchStatus status;
02318
02319 reply = check_for_reply_unlocked (connection,
02320 _dbus_pending_call_get_reply_serial_unlocked (pending));
02321 if (reply != NULL)
02322 {
02323 _dbus_verbose ("checked for reply\n");
02324
02325 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02326
02327 complete_pending_call_and_unlock (connection, pending, reply);
02328 dbus_message_unref (reply);
02329
02330 CONNECTION_LOCK (connection);
02331 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02332 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02333 dbus_pending_call_unref (pending);
02334
02335 return TRUE;
02336 }
02337
02338 return FALSE;
02339 }
02340
02355 void
02356 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02357 {
02358 long start_tv_sec, start_tv_usec;
02359 long tv_sec, tv_usec;
02360 DBusDispatchStatus status;
02361 DBusConnection *connection;
02362 dbus_uint32_t client_serial;
02363 DBusTimeout *timeout;
02364 int timeout_milliseconds, elapsed_milliseconds;
02365
02366 _dbus_assert (pending != NULL);
02367
02368 if (dbus_pending_call_get_completed (pending))
02369 return;
02370
02371 dbus_pending_call_ref (pending);
02372
02373 connection = _dbus_pending_call_get_connection_and_lock (pending);
02374
02375
02376 _dbus_connection_flush_unlocked (connection);
02377
02378 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02379
02380
02381
02382
02383
02384 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02385 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02386 if (timeout)
02387 {
02388 timeout_milliseconds = dbus_timeout_get_interval (timeout);
02389
02390 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02391 timeout_milliseconds,
02392 client_serial,
02393 start_tv_sec, start_tv_usec);
02394 }
02395 else
02396 {
02397 timeout_milliseconds = -1;
02398
02399 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02400 }
02401
02402
02403
02404 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02405 return;
02406
02407
02408
02409 _dbus_connection_do_iteration_unlocked (connection,
02410 pending,
02411 DBUS_ITERATION_DO_READING |
02412 DBUS_ITERATION_BLOCK,
02413 timeout_milliseconds);
02414
02415 recheck_status:
02416
02417 _dbus_verbose ("top of recheck\n");
02418
02419 HAVE_LOCK_CHECK (connection);
02420
02421
02422
02423 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02424
02425
02426
02427
02428 if (_dbus_pending_call_get_completed_unlocked (pending))
02429 {
02430 _dbus_verbose ("Pending call completed by dispatch\n");
02431 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02432 dbus_pending_call_unref (pending);
02433 return;
02434 }
02435
02436 if (status == DBUS_DISPATCH_DATA_REMAINS)
02437 {
02438 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02439 return;
02440 }
02441
02442 _dbus_get_current_time (&tv_sec, &tv_usec);
02443 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02444 (tv_usec - start_tv_usec) / 1000;
02445
02446 if (!_dbus_connection_get_is_connected_unlocked (connection))
02447 {
02448 DBusMessage *error_msg;
02449
02450 error_msg = generate_local_error_message (client_serial,
02451 DBUS_ERROR_DISCONNECTED,
02452 "Connection was disconnected before a reply was received");
02453
02454
02455 complete_pending_call_and_unlock (connection, pending, error_msg);
02456 dbus_pending_call_unref (pending);
02457 return;
02458 }
02459 else if (connection->disconnect_message_link == NULL)
02460 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02461 else if (timeout == NULL)
02462 {
02463 if (status == DBUS_DISPATCH_NEED_MEMORY)
02464 {
02465
02466
02467
02468
02469 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02470
02471 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02472 }
02473 else
02474 {
02475
02476 _dbus_connection_do_iteration_unlocked (connection,
02477 pending,
02478 DBUS_ITERATION_DO_READING |
02479 DBUS_ITERATION_BLOCK,
02480 timeout_milliseconds - elapsed_milliseconds);
02481 }
02482
02483 goto recheck_status;
02484 }
02485 else if (tv_sec < start_tv_sec)
02486 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02487 else if (elapsed_milliseconds < timeout_milliseconds)
02488 {
02489 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02490
02491 if (status == DBUS_DISPATCH_NEED_MEMORY)
02492 {
02493
02494
02495
02496
02497 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02498
02499 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02500 }
02501 else
02502 {
02503
02504 _dbus_connection_do_iteration_unlocked (connection,
02505 NULL,
02506 DBUS_ITERATION_DO_READING |
02507 DBUS_ITERATION_BLOCK,
02508 timeout_milliseconds - elapsed_milliseconds);
02509 }
02510
02511 goto recheck_status;
02512 }
02513
02514 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02515 elapsed_milliseconds);
02516
02517 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02518
02519
02520 complete_pending_call_and_unlock (connection, pending, NULL);
02521
02522
02523 CONNECTION_LOCK (connection);
02524 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02525 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02526 dbus_pending_call_unref (pending);
02527 }
02528
02534 int
02535 _dbus_connection_get_pending_fds_count (DBusConnection *connection)
02536 {
02537 return _dbus_transport_get_pending_fds_count (connection->transport);
02538 }
02539
02547 void
02548 _dbus_connection_set_pending_fds_function (DBusConnection *connection,
02549 DBusPendingFdsChangeFunction callback,
02550 void *data)
02551 {
02552 _dbus_transport_set_pending_fds_function (connection->transport,
02553 callback, data);
02554 }
02555
02592 DBusConnection*
02593 dbus_connection_open (const char *address,
02594 DBusError *error)
02595 {
02596 DBusConnection *connection;
02597
02598 _dbus_return_val_if_fail (address != NULL, NULL);
02599 _dbus_return_val_if_error_is_set (error, NULL);
02600
02601 connection = _dbus_connection_open_internal (address,
02602 TRUE,
02603 error);
02604
02605 return connection;
02606 }
02607
02635 DBusConnection*
02636 dbus_connection_open_private (const char *address,
02637 DBusError *error)
02638 {
02639 DBusConnection *connection;
02640
02641 _dbus_return_val_if_fail (address != NULL, NULL);
02642 _dbus_return_val_if_error_is_set (error, NULL);
02643
02644 connection = _dbus_connection_open_internal (address,
02645 FALSE,
02646 error);
02647
02648 return connection;
02649 }
02650
02657 DBusConnection *
02658 dbus_connection_ref (DBusConnection *connection)
02659 {
02660 _dbus_return_val_if_fail (connection != NULL, NULL);
02661 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672 #if 1
02673 _dbus_atomic_inc (&connection->refcount);
02674 #else
02675 CONNECTION_LOCK (connection);
02676 _dbus_assert (connection->refcount.value > 0);
02677
02678 connection->refcount.value += 1;
02679 CONNECTION_UNLOCK (connection);
02680 #endif
02681
02682 return connection;
02683 }
02684
02685 static void
02686 free_outgoing_message (void *element,
02687 void *data)
02688 {
02689 DBusMessage *message = element;
02690 DBusConnection *connection = data;
02691
02692 _dbus_message_remove_counter (message,
02693 connection->outgoing_counter,
02694 NULL);
02695 dbus_message_unref (message);
02696 }
02697
02698
02699
02700
02701
02702 static void
02703 _dbus_connection_last_unref (DBusConnection *connection)
02704 {
02705 DBusList *link;
02706
02707 _dbus_verbose ("Finalizing connection %p\n", connection);
02708
02709 _dbus_assert (connection->refcount.value == 0);
02710
02711
02712
02713
02714 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02715 _dbus_assert (connection->server_guid == NULL);
02716
02717
02718 _dbus_object_tree_free_all_unlocked (connection->objects);
02719
02720 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02721 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02722 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02723
02724 _dbus_watch_list_free (connection->watches);
02725 connection->watches = NULL;
02726
02727 _dbus_timeout_list_free (connection->timeouts);
02728 connection->timeouts = NULL;
02729
02730 _dbus_data_slot_list_free (&connection->slot_list);
02731
02732 link = _dbus_list_get_first_link (&connection->filter_list);
02733 while (link != NULL)
02734 {
02735 DBusMessageFilter *filter = link->data;
02736 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02737
02738 filter->function = NULL;
02739 _dbus_message_filter_unref (filter);
02740 link->data = NULL;
02741
02742 link = next;
02743 }
02744 _dbus_list_clear (&connection->filter_list);
02745
02746
02747
02748 _dbus_object_tree_unref (connection->objects);
02749
02750 _dbus_hash_table_unref (connection->pending_replies);
02751 connection->pending_replies = NULL;
02752
02753 _dbus_list_clear (&connection->filter_list);
02754
02755 _dbus_list_foreach (&connection->outgoing_messages,
02756 free_outgoing_message,
02757 connection);
02758 _dbus_list_clear (&connection->outgoing_messages);
02759
02760 _dbus_list_foreach (&connection->incoming_messages,
02761 (DBusForeachFunction) dbus_message_unref,
02762 NULL);
02763 _dbus_list_clear (&connection->incoming_messages);
02764
02765 _dbus_counter_unref (connection->outgoing_counter);
02766
02767 _dbus_transport_unref (connection->transport);
02768
02769 if (connection->disconnect_message_link)
02770 {
02771 DBusMessage *message = connection->disconnect_message_link->data;
02772 dbus_message_unref (message);
02773 _dbus_list_free_link (connection->disconnect_message_link);
02774 }
02775
02776 _dbus_list_clear (&connection->link_cache);
02777
02778 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02779 _dbus_condvar_free_at_location (&connection->io_path_cond);
02780
02781 _dbus_mutex_free_at_location (&connection->io_path_mutex);
02782 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02783
02784 _dbus_mutex_free_at_location (&connection->slot_mutex);
02785
02786 _dbus_mutex_free_at_location (&connection->mutex);
02787
02788 dbus_free (connection);
02789 }
02790
02810 void
02811 dbus_connection_unref (DBusConnection *connection)
02812 {
02813 dbus_bool_t last_unref;
02814
02815 _dbus_return_if_fail (connection != NULL);
02816 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827 #if 1
02828 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02829 #else
02830 CONNECTION_LOCK (connection);
02831
02832 _dbus_assert (connection->refcount.value > 0);
02833
02834 connection->refcount.value -= 1;
02835 last_unref = (connection->refcount.value == 0);
02836
02837 #if 0
02838 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02839 #endif
02840
02841 CONNECTION_UNLOCK (connection);
02842 #endif
02843
02844 if (last_unref)
02845 {
02846 #ifndef DBUS_DISABLE_CHECKS
02847 if (_dbus_transport_get_is_connected (connection->transport))
02848 {
02849 _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",
02850 connection->shareable ?
02851 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02852 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02853 return;
02854 }
02855 #endif
02856 _dbus_connection_last_unref (connection);
02857 }
02858 }
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869 static void
02870 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02871 {
02872 DBusDispatchStatus status;
02873
02874 HAVE_LOCK_CHECK (connection);
02875
02876 _dbus_verbose ("Disconnecting %p\n", connection);
02877
02878
02879
02880
02881
02882 _dbus_connection_ref_unlocked (connection);
02883
02884 _dbus_transport_disconnect (connection->transport);
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02896
02897
02898 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02899
02900
02901 dbus_connection_unref (connection);
02902 }
02903
02946 void
02947 dbus_connection_close (DBusConnection *connection)
02948 {
02949 _dbus_return_if_fail (connection != NULL);
02950 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02951
02952 CONNECTION_LOCK (connection);
02953
02954 #ifndef DBUS_DISABLE_CHECKS
02955 if (connection->shareable)
02956 {
02957 CONNECTION_UNLOCK (connection);
02958
02959 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02960 return;
02961 }
02962 #endif
02963
02964 _dbus_connection_close_possibly_shared_and_unlock (connection);
02965 }
02966
02967 static dbus_bool_t
02968 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02969 {
02970 HAVE_LOCK_CHECK (connection);
02971 return _dbus_transport_get_is_connected (connection->transport);
02972 }
02973
02987 dbus_bool_t
02988 dbus_connection_get_is_connected (DBusConnection *connection)
02989 {
02990 dbus_bool_t res;
02991
02992 _dbus_return_val_if_fail (connection != NULL, FALSE);
02993
02994 CONNECTION_LOCK (connection);
02995 res = _dbus_connection_get_is_connected_unlocked (connection);
02996 CONNECTION_UNLOCK (connection);
02997
02998 return res;
02999 }
03000
03009 dbus_bool_t
03010 dbus_connection_get_is_authenticated (DBusConnection *connection)
03011 {
03012 dbus_bool_t res;
03013
03014 _dbus_return_val_if_fail (connection != NULL, FALSE);
03015
03016 CONNECTION_LOCK (connection);
03017 res = _dbus_transport_get_is_authenticated (connection->transport);
03018 CONNECTION_UNLOCK (connection);
03019
03020 return res;
03021 }
03022
03043 dbus_bool_t
03044 dbus_connection_get_is_anonymous (DBusConnection *connection)
03045 {
03046 dbus_bool_t res;
03047
03048 _dbus_return_val_if_fail (connection != NULL, FALSE);
03049
03050 CONNECTION_LOCK (connection);
03051 res = _dbus_transport_get_is_anonymous (connection->transport);
03052 CONNECTION_UNLOCK (connection);
03053
03054 return res;
03055 }
03056
03088 char*
03089 dbus_connection_get_server_id (DBusConnection *connection)
03090 {
03091 char *id;
03092
03093 _dbus_return_val_if_fail (connection != NULL, NULL);
03094
03095 CONNECTION_LOCK (connection);
03096 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03097 CONNECTION_UNLOCK (connection);
03098
03099 return id;
03100 }
03101
03119 dbus_bool_t
03120 dbus_connection_can_send_type(DBusConnection *connection,
03121 int type)
03122 {
03123 _dbus_return_val_if_fail (connection != NULL, FALSE);
03124
03125 if (!_dbus_type_is_valid(type))
03126 return FALSE;
03127
03128 if (type != DBUS_TYPE_UNIX_FD)
03129 return TRUE;
03130
03131 #ifdef HAVE_UNIX_FD_PASSING
03132 {
03133 dbus_bool_t b;
03134
03135 CONNECTION_LOCK(connection);
03136 b = _dbus_transport_can_pass_unix_fd(connection->transport);
03137 CONNECTION_UNLOCK(connection);
03138
03139 return b;
03140 }
03141 #endif
03142
03143 return FALSE;
03144 }
03145
03159 void
03160 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03161 dbus_bool_t exit_on_disconnect)
03162 {
03163 _dbus_return_if_fail (connection != NULL);
03164
03165 CONNECTION_LOCK (connection);
03166 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03167 CONNECTION_UNLOCK (connection);
03168 }
03169
03179 DBusPreallocatedSend*
03180 dbus_connection_preallocate_send (DBusConnection *connection)
03181 {
03182 DBusPreallocatedSend *preallocated;
03183
03184 _dbus_return_val_if_fail (connection != NULL, NULL);
03185
03186 CONNECTION_LOCK (connection);
03187
03188 preallocated =
03189 _dbus_connection_preallocate_send_unlocked (connection);
03190
03191 CONNECTION_UNLOCK (connection);
03192
03193 return preallocated;
03194 }
03195
03205 void
03206 dbus_connection_free_preallocated_send (DBusConnection *connection,
03207 DBusPreallocatedSend *preallocated)
03208 {
03209 _dbus_return_if_fail (connection != NULL);
03210 _dbus_return_if_fail (preallocated != NULL);
03211 _dbus_return_if_fail (connection == preallocated->connection);
03212
03213 _dbus_list_free_link (preallocated->queue_link);
03214 _dbus_counter_unref (preallocated->counter_link->data);
03215 _dbus_list_free_link (preallocated->counter_link);
03216 dbus_free (preallocated);
03217 }
03218
03231 void
03232 dbus_connection_send_preallocated (DBusConnection *connection,
03233 DBusPreallocatedSend *preallocated,
03234 DBusMessage *message,
03235 dbus_uint32_t *client_serial)
03236 {
03237 _dbus_return_if_fail (connection != NULL);
03238 _dbus_return_if_fail (preallocated != NULL);
03239 _dbus_return_if_fail (message != NULL);
03240 _dbus_return_if_fail (preallocated->connection == connection);
03241 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03242 dbus_message_get_member (message) != NULL);
03243 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03244 (dbus_message_get_interface (message) != NULL &&
03245 dbus_message_get_member (message) != NULL));
03246
03247 CONNECTION_LOCK (connection);
03248
03249 #ifdef HAVE_UNIX_FD_PASSING
03250
03251 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03252 message->n_unix_fds > 0)
03253 {
03254
03255
03256
03257 CONNECTION_UNLOCK (connection);
03258 return;
03259 }
03260
03261 #endif
03262
03263 _dbus_connection_send_preallocated_and_unlock (connection,
03264 preallocated,
03265 message, client_serial);
03266 }
03267
03268 static dbus_bool_t
03269 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03270 DBusMessage *message,
03271 dbus_uint32_t *client_serial)
03272 {
03273 DBusPreallocatedSend *preallocated;
03274
03275 _dbus_assert (connection != NULL);
03276 _dbus_assert (message != NULL);
03277
03278 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03279 if (preallocated == NULL)
03280 return FALSE;
03281
03282 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03283 preallocated,
03284 message,
03285 client_serial);
03286 return TRUE;
03287 }
03288
03316 dbus_bool_t
03317 dbus_connection_send (DBusConnection *connection,
03318 DBusMessage *message,
03319 dbus_uint32_t *serial)
03320 {
03321 _dbus_return_val_if_fail (connection != NULL, FALSE);
03322 _dbus_return_val_if_fail (message != NULL, FALSE);
03323
03324 CONNECTION_LOCK (connection);
03325
03326 #ifdef HAVE_UNIX_FD_PASSING
03327
03328 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03329 message->n_unix_fds > 0)
03330 {
03331
03332
03333
03334 CONNECTION_UNLOCK (connection);
03335 return FALSE;
03336 }
03337
03338 #endif
03339
03340 return _dbus_connection_send_and_unlock (connection,
03341 message,
03342 serial);
03343 }
03344
03345 static dbus_bool_t
03346 reply_handler_timeout (void *data)
03347 {
03348 DBusConnection *connection;
03349 DBusDispatchStatus status;
03350 DBusPendingCall *pending = data;
03351
03352 connection = _dbus_pending_call_get_connection_and_lock (pending);
03353
03354 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03355 connection);
03356 _dbus_connection_remove_timeout_unlocked (connection,
03357 _dbus_pending_call_get_timeout_unlocked (pending));
03358 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03359
03360 _dbus_verbose ("middle\n");
03361 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03362
03363
03364 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03365
03366 return TRUE;
03367 }
03368
03408 dbus_bool_t
03409 dbus_connection_send_with_reply (DBusConnection *connection,
03410 DBusMessage *message,
03411 DBusPendingCall **pending_return,
03412 int timeout_milliseconds)
03413 {
03414 DBusPendingCall *pending;
03415 dbus_int32_t serial = -1;
03416 DBusDispatchStatus status;
03417
03418 _dbus_return_val_if_fail (connection != NULL, FALSE);
03419 _dbus_return_val_if_fail (message != NULL, FALSE);
03420 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03421
03422 if (pending_return)
03423 *pending_return = NULL;
03424
03425 CONNECTION_LOCK (connection);
03426
03427 #ifdef HAVE_UNIX_FD_PASSING
03428
03429 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03430 message->n_unix_fds > 0)
03431 {
03432
03433
03434
03435
03436 CONNECTION_UNLOCK (connection);
03437 return TRUE;
03438 }
03439
03440 #endif
03441
03442 if (!_dbus_connection_get_is_connected_unlocked (connection))
03443 {
03444 CONNECTION_UNLOCK (connection);
03445
03446 return TRUE;
03447 }
03448
03449 pending = _dbus_pending_call_new_unlocked (connection,
03450 timeout_milliseconds,
03451 reply_handler_timeout);
03452
03453 if (pending == NULL)
03454 {
03455 CONNECTION_UNLOCK (connection);
03456 return FALSE;
03457 }
03458
03459
03460 serial = dbus_message_get_serial (message);
03461 if (serial == 0)
03462 {
03463 serial = _dbus_connection_get_next_client_serial (connection);
03464 dbus_message_set_serial (message, serial);
03465 }
03466
03467 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03468 goto error;
03469
03470
03471
03472
03473
03474 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03475 pending))
03476 goto error;
03477
03478 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03479 {
03480 _dbus_connection_detach_pending_call_and_unlock (connection,
03481 pending);
03482 goto error_unlocked;
03483 }
03484
03485 if (pending_return)
03486 *pending_return = pending;
03487 else
03488 {
03489 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03490
03491
03492
03493 }
03494
03495 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03496
03497
03498 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03499
03500 if (pending_return == NULL)
03501 dbus_pending_call_unref (pending);
03502
03503 return TRUE;
03504
03505 error:
03506 CONNECTION_UNLOCK (connection);
03507 error_unlocked:
03508 dbus_pending_call_unref (pending);
03509 return FALSE;
03510 }
03511
03542 DBusMessage*
03543 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03544 DBusMessage *message,
03545 int timeout_milliseconds,
03546 DBusError *error)
03547 {
03548 DBusMessage *reply;
03549 DBusPendingCall *pending;
03550
03551 _dbus_return_val_if_fail (connection != NULL, NULL);
03552 _dbus_return_val_if_fail (message != NULL, NULL);
03553 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03554 _dbus_return_val_if_error_is_set (error, NULL);
03555
03556 #ifdef HAVE_UNIX_FD_PASSING
03557
03558 CONNECTION_LOCK (connection);
03559 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03560 message->n_unix_fds > 0)
03561 {
03562 CONNECTION_UNLOCK (connection);
03563 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03564 return NULL;
03565 }
03566 CONNECTION_UNLOCK (connection);
03567
03568 #endif
03569
03570 if (!dbus_connection_send_with_reply (connection, message,
03571 &pending, timeout_milliseconds))
03572 {
03573 _DBUS_SET_OOM (error);
03574 return NULL;
03575 }
03576
03577 if (pending == NULL)
03578 {
03579 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03580 return NULL;
03581 }
03582
03583 dbus_pending_call_block (pending);
03584
03585 reply = dbus_pending_call_steal_reply (pending);
03586 dbus_pending_call_unref (pending);
03587
03588
03589
03590
03591 _dbus_assert (reply != NULL);
03592
03593 if (dbus_set_error_from_message (error, reply))
03594 {
03595 dbus_message_unref (reply);
03596 return NULL;
03597 }
03598 else
03599 return reply;
03600 }
03601
03610 static DBusDispatchStatus
03611 _dbus_connection_flush_unlocked (DBusConnection *connection)
03612 {
03613
03614
03615
03616
03617
03618 DBusDispatchStatus status;
03619
03620 HAVE_LOCK_CHECK (connection);
03621
03622 while (connection->n_outgoing > 0 &&
03623 _dbus_connection_get_is_connected_unlocked (connection))
03624 {
03625 _dbus_verbose ("doing iteration in\n");
03626 HAVE_LOCK_CHECK (connection);
03627 _dbus_connection_do_iteration_unlocked (connection,
03628 NULL,
03629 DBUS_ITERATION_DO_READING |
03630 DBUS_ITERATION_DO_WRITING |
03631 DBUS_ITERATION_BLOCK,
03632 -1);
03633 }
03634
03635 HAVE_LOCK_CHECK (connection);
03636 _dbus_verbose ("middle\n");
03637 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03638
03639 HAVE_LOCK_CHECK (connection);
03640 return status;
03641 }
03642
03648 void
03649 dbus_connection_flush (DBusConnection *connection)
03650 {
03651
03652
03653
03654
03655
03656 DBusDispatchStatus status;
03657
03658 _dbus_return_if_fail (connection != NULL);
03659
03660 CONNECTION_LOCK (connection);
03661
03662 status = _dbus_connection_flush_unlocked (connection);
03663
03664 HAVE_LOCK_CHECK (connection);
03665
03666 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03667
03668 _dbus_verbose ("end\n");
03669 }
03670
03681 static dbus_bool_t
03682 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03683 int timeout_milliseconds,
03684 dbus_bool_t dispatch)
03685 {
03686 DBusDispatchStatus dstatus;
03687 dbus_bool_t progress_possible;
03688
03689
03690
03691
03692
03693 dbus_connection_ref (connection);
03694 dstatus = dbus_connection_get_dispatch_status (connection);
03695
03696 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03697 {
03698 _dbus_verbose ("doing dispatch\n");
03699 dbus_connection_dispatch (connection);
03700 CONNECTION_LOCK (connection);
03701 }
03702 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03703 {
03704 _dbus_verbose ("pausing for memory\n");
03705 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03706 CONNECTION_LOCK (connection);
03707 }
03708 else
03709 {
03710 CONNECTION_LOCK (connection);
03711 if (_dbus_connection_get_is_connected_unlocked (connection))
03712 {
03713 _dbus_verbose ("doing iteration\n");
03714 _dbus_connection_do_iteration_unlocked (connection,
03715 NULL,
03716 DBUS_ITERATION_DO_READING |
03717 DBUS_ITERATION_DO_WRITING |
03718 DBUS_ITERATION_BLOCK,
03719 timeout_milliseconds);
03720 }
03721 }
03722
03723 HAVE_LOCK_CHECK (connection);
03724
03725
03726
03727
03728 if (dispatch)
03729 progress_possible = connection->n_incoming != 0 ||
03730 connection->disconnect_message_link != NULL;
03731 else
03732 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03733
03734 CONNECTION_UNLOCK (connection);
03735
03736 dbus_connection_unref (connection);
03737
03738 return progress_possible;
03739 }
03740
03741
03776 dbus_bool_t
03777 dbus_connection_read_write_dispatch (DBusConnection *connection,
03778 int timeout_milliseconds)
03779 {
03780 _dbus_return_val_if_fail (connection != NULL, FALSE);
03781 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03782 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03783 }
03784
03808 dbus_bool_t
03809 dbus_connection_read_write (DBusConnection *connection,
03810 int timeout_milliseconds)
03811 {
03812 _dbus_return_val_if_fail (connection != NULL, FALSE);
03813 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03814 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03815 }
03816
03817
03818
03819
03820
03821
03822 static void
03823 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03824 DBusMessage *head_of_queue)
03825 {
03826 HAVE_LOCK_CHECK (connection);
03827
03828
03829 if (connection->disconnect_message_link == NULL &&
03830 dbus_message_is_signal (head_of_queue,
03831 DBUS_INTERFACE_LOCAL,
03832 "Disconnected"))
03833 {
03834 connection->disconnected_message_arrived = TRUE;
03835 }
03836 }
03837
03857 DBusMessage*
03858 dbus_connection_borrow_message (DBusConnection *connection)
03859 {
03860 DBusDispatchStatus status;
03861 DBusMessage *message;
03862
03863 _dbus_return_val_if_fail (connection != NULL, NULL);
03864
03865 _dbus_verbose ("start\n");
03866
03867
03868
03869
03870 status = dbus_connection_get_dispatch_status (connection);
03871 if (status != DBUS_DISPATCH_DATA_REMAINS)
03872 return NULL;
03873
03874 CONNECTION_LOCK (connection);
03875
03876 _dbus_connection_acquire_dispatch (connection);
03877
03878
03879 _dbus_assert (connection->message_borrowed == NULL);
03880
03881 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03882
03883 message = connection->message_borrowed;
03884
03885 check_disconnected_message_arrived_unlocked (connection, message);
03886
03887
03888 if (message == NULL)
03889 _dbus_connection_release_dispatch (connection);
03890
03891 CONNECTION_UNLOCK (connection);
03892
03893
03894
03895 return message;
03896 }
03897
03906 void
03907 dbus_connection_return_message (DBusConnection *connection,
03908 DBusMessage *message)
03909 {
03910 DBusDispatchStatus status;
03911
03912 _dbus_return_if_fail (connection != NULL);
03913 _dbus_return_if_fail (message != NULL);
03914 _dbus_return_if_fail (message == connection->message_borrowed);
03915 _dbus_return_if_fail (connection->dispatch_acquired);
03916
03917 CONNECTION_LOCK (connection);
03918
03919 _dbus_assert (message == connection->message_borrowed);
03920
03921 connection->message_borrowed = NULL;
03922
03923 _dbus_connection_release_dispatch (connection);
03924
03925 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03926 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03927 }
03928
03938 void
03939 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03940 DBusMessage *message)
03941 {
03942 DBusMessage *pop_message;
03943 DBusDispatchStatus status;
03944
03945 _dbus_return_if_fail (connection != NULL);
03946 _dbus_return_if_fail (message != NULL);
03947 _dbus_return_if_fail (message == connection->message_borrowed);
03948 _dbus_return_if_fail (connection->dispatch_acquired);
03949
03950 CONNECTION_LOCK (connection);
03951
03952 _dbus_assert (message == connection->message_borrowed);
03953
03954 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03955 _dbus_assert (message == pop_message);
03956
03957 connection->n_incoming -= 1;
03958
03959 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03960 message, connection->n_incoming);
03961
03962 connection->message_borrowed = NULL;
03963
03964 _dbus_connection_release_dispatch (connection);
03965
03966 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03967 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03968 }
03969
03970
03971
03972
03973 static DBusList*
03974 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03975 {
03976 HAVE_LOCK_CHECK (connection);
03977
03978 _dbus_assert (connection->message_borrowed == NULL);
03979
03980 if (connection->n_incoming > 0)
03981 {
03982 DBusList *link;
03983
03984 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03985 connection->n_incoming -= 1;
03986
03987 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03988 link->data,
03989 dbus_message_type_to_string (dbus_message_get_type (link->data)),
03990 dbus_message_get_path (link->data) ?
03991 dbus_message_get_path (link->data) :
03992 "no path",
03993 dbus_message_get_interface (link->data) ?
03994 dbus_message_get_interface (link->data) :
03995 "no interface",
03996 dbus_message_get_member (link->data) ?
03997 dbus_message_get_member (link->data) :
03998 "no member",
03999 dbus_message_get_signature (link->data),
04000 connection, connection->n_incoming);
04001
04002 check_disconnected_message_arrived_unlocked (connection, link->data);
04003
04004 return link;
04005 }
04006 else
04007 return NULL;
04008 }
04009
04010
04011
04012
04013 static DBusMessage*
04014 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
04015 {
04016 DBusList *link;
04017
04018 HAVE_LOCK_CHECK (connection);
04019
04020 link = _dbus_connection_pop_message_link_unlocked (connection);
04021
04022 if (link != NULL)
04023 {
04024 DBusMessage *message;
04025
04026 message = link->data;
04027
04028 _dbus_list_free_link (link);
04029
04030 return message;
04031 }
04032 else
04033 return NULL;
04034 }
04035
04036 static void
04037 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
04038 DBusList *message_link)
04039 {
04040 HAVE_LOCK_CHECK (connection);
04041
04042 _dbus_assert (message_link != NULL);
04043
04044 _dbus_assert (connection->message_borrowed == NULL);
04045
04046 _dbus_assert (connection->dispatch_acquired);
04047
04048 _dbus_list_prepend_link (&connection->incoming_messages,
04049 message_link);
04050 connection->n_incoming += 1;
04051
04052 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
04053 message_link->data,
04054 dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
04055 dbus_message_get_interface (message_link->data) ?
04056 dbus_message_get_interface (message_link->data) :
04057 "no interface",
04058 dbus_message_get_member (message_link->data) ?
04059 dbus_message_get_member (message_link->data) :
04060 "no member",
04061 dbus_message_get_signature (message_link->data),
04062 connection, connection->n_incoming);
04063 }
04064
04084 DBusMessage*
04085 dbus_connection_pop_message (DBusConnection *connection)
04086 {
04087 DBusMessage *message;
04088 DBusDispatchStatus status;
04089
04090 _dbus_verbose ("start\n");
04091
04092
04093
04094
04095 status = dbus_connection_get_dispatch_status (connection);
04096 if (status != DBUS_DISPATCH_DATA_REMAINS)
04097 return NULL;
04098
04099 CONNECTION_LOCK (connection);
04100 _dbus_connection_acquire_dispatch (connection);
04101 HAVE_LOCK_CHECK (connection);
04102
04103 message = _dbus_connection_pop_message_unlocked (connection);
04104
04105 _dbus_verbose ("Returning popped message %p\n", message);
04106
04107 _dbus_connection_release_dispatch (connection);
04108
04109 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04110 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04111
04112 return message;
04113 }
04114
04122 static void
04123 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04124 {
04125 HAVE_LOCK_CHECK (connection);
04126
04127 _dbus_connection_ref_unlocked (connection);
04128 CONNECTION_UNLOCK (connection);
04129
04130 _dbus_verbose ("locking dispatch_mutex\n");
04131 _dbus_mutex_lock (connection->dispatch_mutex);
04132
04133 while (connection->dispatch_acquired)
04134 {
04135 _dbus_verbose ("waiting for dispatch to be acquirable\n");
04136 _dbus_condvar_wait (connection->dispatch_cond,
04137 connection->dispatch_mutex);
04138 }
04139
04140 _dbus_assert (!connection->dispatch_acquired);
04141
04142 connection->dispatch_acquired = TRUE;
04143
04144 _dbus_verbose ("unlocking dispatch_mutex\n");
04145 _dbus_mutex_unlock (connection->dispatch_mutex);
04146
04147 CONNECTION_LOCK (connection);
04148 _dbus_connection_unref_unlocked (connection);
04149 }
04150
04158 static void
04159 _dbus_connection_release_dispatch (DBusConnection *connection)
04160 {
04161 HAVE_LOCK_CHECK (connection);
04162
04163 _dbus_verbose ("locking dispatch_mutex\n");
04164 _dbus_mutex_lock (connection->dispatch_mutex);
04165
04166 _dbus_assert (connection->dispatch_acquired);
04167
04168 connection->dispatch_acquired = FALSE;
04169 _dbus_condvar_wake_one (connection->dispatch_cond);
04170
04171 _dbus_verbose ("unlocking dispatch_mutex\n");
04172 _dbus_mutex_unlock (connection->dispatch_mutex);
04173 }
04174
04175 static void
04176 _dbus_connection_failed_pop (DBusConnection *connection,
04177 DBusList *message_link)
04178 {
04179 _dbus_list_prepend_link (&connection->incoming_messages,
04180 message_link);
04181 connection->n_incoming += 1;
04182 }
04183
04184
04185 static void
04186 notify_disconnected_unlocked (DBusConnection *connection)
04187 {
04188 HAVE_LOCK_CHECK (connection);
04189
04190
04191
04192
04193
04194
04195
04196 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04197
04198
04199
04200
04201
04202 if (connection->n_outgoing > 0)
04203 {
04204 DBusList *link;
04205
04206 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04207 connection->n_outgoing);
04208
04209 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04210 {
04211 _dbus_connection_message_sent (connection, link->data);
04212 }
04213 }
04214 }
04215
04216
04217 static DBusDispatchStatus
04218 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04219 {
04220 HAVE_LOCK_CHECK (connection);
04221
04222 if (connection->disconnect_message_link != NULL)
04223 {
04224 _dbus_verbose ("Sending disconnect message\n");
04225
04226
04227
04228
04229 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04230
04231
04232
04233
04234 _dbus_connection_queue_synthesized_message_link (connection,
04235 connection->disconnect_message_link);
04236 connection->disconnect_message_link = NULL;
04237
04238 return DBUS_DISPATCH_DATA_REMAINS;
04239 }
04240
04241 return DBUS_DISPATCH_COMPLETE;
04242 }
04243
04244 static DBusDispatchStatus
04245 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04246 {
04247 HAVE_LOCK_CHECK (connection);
04248
04249 if (connection->n_incoming > 0)
04250 return DBUS_DISPATCH_DATA_REMAINS;
04251 else if (!_dbus_transport_queue_messages (connection->transport))
04252 return DBUS_DISPATCH_NEED_MEMORY;
04253 else
04254 {
04255 DBusDispatchStatus status;
04256 dbus_bool_t is_connected;
04257
04258 status = _dbus_transport_get_dispatch_status (connection->transport);
04259 is_connected = _dbus_transport_get_is_connected (connection->transport);
04260
04261 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04262 DISPATCH_STATUS_NAME (status), is_connected);
04263
04264 if (!is_connected)
04265 {
04266
04267
04268
04269
04270
04271
04272 notify_disconnected_unlocked (connection);
04273
04274
04275
04276
04277
04278
04279 if (status == DBUS_DISPATCH_COMPLETE)
04280 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04281 }
04282
04283 if (status != DBUS_DISPATCH_COMPLETE)
04284 return status;
04285 else if (connection->n_incoming > 0)
04286 return DBUS_DISPATCH_DATA_REMAINS;
04287 else
04288 return DBUS_DISPATCH_COMPLETE;
04289 }
04290 }
04291
04292 static void
04293 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04294 DBusDispatchStatus new_status)
04295 {
04296 dbus_bool_t changed;
04297 DBusDispatchStatusFunction function;
04298 void *data;
04299
04300 HAVE_LOCK_CHECK (connection);
04301
04302 _dbus_connection_ref_unlocked (connection);
04303
04304 changed = new_status != connection->last_dispatch_status;
04305
04306 connection->last_dispatch_status = new_status;
04307
04308 function = connection->dispatch_status_function;
04309 data = connection->dispatch_status_data;
04310
04311 if (connection->disconnected_message_arrived &&
04312 !connection->disconnected_message_processed)
04313 {
04314 connection->disconnected_message_processed = TRUE;
04315
04316
04317
04318
04319
04320 connection_forget_shared_unlocked (connection);
04321
04322 if (connection->exit_on_disconnect)
04323 {
04324 CONNECTION_UNLOCK (connection);
04325
04326 _dbus_verbose ("Exiting on Disconnected signal\n");
04327 _dbus_exit (1);
04328 _dbus_assert_not_reached ("Call to exit() returned");
04329 }
04330 }
04331
04332
04333 CONNECTION_UNLOCK (connection);
04334
04335 if (changed && function)
04336 {
04337 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04338 connection, new_status,
04339 DISPATCH_STATUS_NAME (new_status));
04340 (* function) (connection, new_status, data);
04341 }
04342
04343 dbus_connection_unref (connection);
04344 }
04345
04371 DBusDispatchStatus
04372 dbus_connection_get_dispatch_status (DBusConnection *connection)
04373 {
04374 DBusDispatchStatus status;
04375
04376 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04377
04378 _dbus_verbose ("start\n");
04379
04380 CONNECTION_LOCK (connection);
04381
04382 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04383
04384 CONNECTION_UNLOCK (connection);
04385
04386 return status;
04387 }
04388
04392 static DBusHandlerResult
04393 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04394 DBusMessage *message)
04395 {
04396 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04397 {
04398
04399 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04400 }
04401 else if (dbus_message_is_method_call (message,
04402 DBUS_INTERFACE_PEER,
04403 "Ping"))
04404 {
04405 DBusMessage *ret;
04406 dbus_bool_t sent;
04407
04408 ret = dbus_message_new_method_return (message);
04409 if (ret == NULL)
04410 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04411
04412 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04413
04414 dbus_message_unref (ret);
04415
04416 if (!sent)
04417 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04418
04419 return DBUS_HANDLER_RESULT_HANDLED;
04420 }
04421 else if (dbus_message_is_method_call (message,
04422 DBUS_INTERFACE_PEER,
04423 "GetMachineId"))
04424 {
04425 DBusMessage *ret;
04426 dbus_bool_t sent;
04427 DBusString uuid;
04428
04429 ret = dbus_message_new_method_return (message);
04430 if (ret == NULL)
04431 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04432
04433 sent = FALSE;
04434 _dbus_string_init (&uuid);
04435 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04436 {
04437 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04438 if (dbus_message_append_args (ret,
04439 DBUS_TYPE_STRING, &v_STRING,
04440 DBUS_TYPE_INVALID))
04441 {
04442 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04443 }
04444 }
04445 _dbus_string_free (&uuid);
04446
04447 dbus_message_unref (ret);
04448
04449 if (!sent)
04450 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04451
04452 return DBUS_HANDLER_RESULT_HANDLED;
04453 }
04454 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04455 {
04456
04457
04458
04459
04460
04461 DBusMessage *ret;
04462 dbus_bool_t sent;
04463
04464 ret = dbus_message_new_error (message,
04465 DBUS_ERROR_UNKNOWN_METHOD,
04466 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04467 if (ret == NULL)
04468 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04469
04470 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04471
04472 dbus_message_unref (ret);
04473
04474 if (!sent)
04475 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04476
04477 return DBUS_HANDLER_RESULT_HANDLED;
04478 }
04479 else
04480 {
04481 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04482 }
04483 }
04484
04491 static DBusHandlerResult
04492 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04493 DBusMessage *message)
04494 {
04495
04496
04497
04498 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04499 }
04500
04543 DBusDispatchStatus
04544 dbus_connection_dispatch (DBusConnection *connection)
04545 {
04546 DBusMessage *message;
04547 DBusList *link, *filter_list_copy, *message_link;
04548 DBusHandlerResult result;
04549 DBusPendingCall *pending;
04550 dbus_int32_t reply_serial;
04551 DBusDispatchStatus status;
04552
04553 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04554
04555 _dbus_verbose ("\n");
04556
04557 CONNECTION_LOCK (connection);
04558 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04559 if (status != DBUS_DISPATCH_DATA_REMAINS)
04560 {
04561
04562 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04563 return status;
04564 }
04565
04566
04567
04568
04569 _dbus_connection_ref_unlocked (connection);
04570
04571 _dbus_connection_acquire_dispatch (connection);
04572 HAVE_LOCK_CHECK (connection);
04573
04574 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04575 if (message_link == NULL)
04576 {
04577
04578
04579 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04580
04581 _dbus_connection_release_dispatch (connection);
04582
04583 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04584
04585 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04586
04587 dbus_connection_unref (connection);
04588
04589 return status;
04590 }
04591
04592 message = message_link->data;
04593
04594 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04595 message,
04596 dbus_message_type_to_string (dbus_message_get_type (message)),
04597 dbus_message_get_interface (message) ?
04598 dbus_message_get_interface (message) :
04599 "no interface",
04600 dbus_message_get_member (message) ?
04601 dbus_message_get_member (message) :
04602 "no member",
04603 dbus_message_get_signature (message));
04604
04605 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04606
04607
04608
04609
04610
04611
04612
04613
04614 reply_serial = dbus_message_get_reply_serial (message);
04615 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04616 reply_serial);
04617 if (pending)
04618 {
04619 _dbus_verbose ("Dispatching a pending reply\n");
04620 complete_pending_call_and_unlock (connection, pending, message);
04621 pending = NULL;
04622
04623 CONNECTION_LOCK (connection);
04624 _dbus_verbose ("pending call completed in dispatch\n");
04625 result = DBUS_HANDLER_RESULT_HANDLED;
04626 goto out;
04627 }
04628
04629 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04630 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04631 goto out;
04632
04633 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04634 {
04635 _dbus_connection_release_dispatch (connection);
04636 HAVE_LOCK_CHECK (connection);
04637
04638 _dbus_connection_failed_pop (connection, message_link);
04639
04640
04641 _dbus_connection_update_dispatch_status_and_unlock (connection,
04642 DBUS_DISPATCH_NEED_MEMORY);
04643
04644 if (pending)
04645 dbus_pending_call_unref (pending);
04646 dbus_connection_unref (connection);
04647
04648 return DBUS_DISPATCH_NEED_MEMORY;
04649 }
04650
04651 _dbus_list_foreach (&filter_list_copy,
04652 (DBusForeachFunction)_dbus_message_filter_ref,
04653 NULL);
04654
04655
04656
04657
04658 CONNECTION_UNLOCK (connection);
04659
04660 link = _dbus_list_get_first_link (&filter_list_copy);
04661 while (link != NULL)
04662 {
04663 DBusMessageFilter *filter = link->data;
04664 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04665
04666 if (filter->function == NULL)
04667 {
04668 _dbus_verbose (" filter was removed in a callback function\n");
04669 link = next;
04670 continue;
04671 }
04672
04673 _dbus_verbose (" running filter on message %p\n", message);
04674 result = (* filter->function) (connection, message, filter->user_data);
04675
04676 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04677 break;
04678
04679 link = next;
04680 }
04681
04682 _dbus_list_foreach (&filter_list_copy,
04683 (DBusForeachFunction)_dbus_message_filter_unref,
04684 NULL);
04685 _dbus_list_clear (&filter_list_copy);
04686
04687 CONNECTION_LOCK (connection);
04688
04689 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04690 {
04691 _dbus_verbose ("No memory\n");
04692 goto out;
04693 }
04694 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04695 {
04696 _dbus_verbose ("filter handled message in dispatch\n");
04697 goto out;
04698 }
04699
04700
04701
04702
04703 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
04704 message,
04705 dbus_message_type_to_string (dbus_message_get_type (message)),
04706 dbus_message_get_interface (message) ?
04707 dbus_message_get_interface (message) :
04708 "no interface",
04709 dbus_message_get_member (message) ?
04710 dbus_message_get_member (message) :
04711 "no member",
04712 dbus_message_get_signature (message));
04713
04714 HAVE_LOCK_CHECK (connection);
04715 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04716 message);
04717
04718 CONNECTION_LOCK (connection);
04719
04720 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04721 {
04722 _dbus_verbose ("object tree handled message in dispatch\n");
04723 goto out;
04724 }
04725
04726 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04727 {
04728 DBusMessage *reply;
04729 DBusString str;
04730 DBusPreallocatedSend *preallocated;
04731
04732 _dbus_verbose (" sending error %s\n",
04733 DBUS_ERROR_UNKNOWN_METHOD);
04734
04735 if (!_dbus_string_init (&str))
04736 {
04737 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04738 _dbus_verbose ("no memory for error string in dispatch\n");
04739 goto out;
04740 }
04741
04742 if (!_dbus_string_append_printf (&str,
04743 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04744 dbus_message_get_member (message),
04745 dbus_message_get_signature (message),
04746 dbus_message_get_interface (message)))
04747 {
04748 _dbus_string_free (&str);
04749 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04750 _dbus_verbose ("no memory for error string in dispatch\n");
04751 goto out;
04752 }
04753
04754 reply = dbus_message_new_error (message,
04755 DBUS_ERROR_UNKNOWN_METHOD,
04756 _dbus_string_get_const_data (&str));
04757 _dbus_string_free (&str);
04758
04759 if (reply == NULL)
04760 {
04761 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04762 _dbus_verbose ("no memory for error reply in dispatch\n");
04763 goto out;
04764 }
04765
04766 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04767
04768 if (preallocated == NULL)
04769 {
04770 dbus_message_unref (reply);
04771 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04772 _dbus_verbose ("no memory for error send in dispatch\n");
04773 goto out;
04774 }
04775
04776 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04777 reply, NULL);
04778
04779 dbus_message_unref (reply);
04780
04781 result = DBUS_HANDLER_RESULT_HANDLED;
04782 }
04783
04784 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04785 dbus_message_type_to_string (dbus_message_get_type (message)),
04786 dbus_message_get_interface (message) ?
04787 dbus_message_get_interface (message) :
04788 "no interface",
04789 dbus_message_get_member (message) ?
04790 dbus_message_get_member (message) :
04791 "no member",
04792 dbus_message_get_signature (message),
04793 connection);
04794
04795 out:
04796 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04797 {
04798 _dbus_verbose ("out of memory\n");
04799
04800
04801
04802
04803
04804 _dbus_connection_putback_message_link_unlocked (connection,
04805 message_link);
04806 }
04807 else
04808 {
04809 _dbus_verbose (" ... done dispatching\n");
04810
04811 _dbus_list_free_link (message_link);
04812 dbus_message_unref (message);
04813
04814
04815 }
04816
04817 _dbus_connection_release_dispatch (connection);
04818 HAVE_LOCK_CHECK (connection);
04819
04820 _dbus_verbose ("before final status update\n");
04821 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04822
04823
04824 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04825
04826 dbus_connection_unref (connection);
04827
04828 return status;
04829 }
04830
04892 dbus_bool_t
04893 dbus_connection_set_watch_functions (DBusConnection *connection,
04894 DBusAddWatchFunction add_function,
04895 DBusRemoveWatchFunction remove_function,
04896 DBusWatchToggledFunction toggled_function,
04897 void *data,
04898 DBusFreeFunction free_data_function)
04899 {
04900 dbus_bool_t retval;
04901
04902 _dbus_return_val_if_fail (connection != NULL, FALSE);
04903
04904 CONNECTION_LOCK (connection);
04905
04906 retval = _dbus_watch_list_set_functions (connection->watches,
04907 add_function, remove_function,
04908 toggled_function,
04909 data, free_data_function);
04910
04911 CONNECTION_UNLOCK (connection);
04912
04913 return retval;
04914 }
04915
04955 dbus_bool_t
04956 dbus_connection_set_timeout_functions (DBusConnection *connection,
04957 DBusAddTimeoutFunction add_function,
04958 DBusRemoveTimeoutFunction remove_function,
04959 DBusTimeoutToggledFunction toggled_function,
04960 void *data,
04961 DBusFreeFunction free_data_function)
04962 {
04963 dbus_bool_t retval;
04964
04965 _dbus_return_val_if_fail (connection != NULL, FALSE);
04966
04967 CONNECTION_LOCK (connection);
04968
04969 retval = _dbus_timeout_list_set_functions (connection->timeouts,
04970 add_function, remove_function,
04971 toggled_function,
04972 data, free_data_function);
04973
04974 CONNECTION_UNLOCK (connection);
04975
04976 return retval;
04977 }
04978
04993 void
04994 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04995 DBusWakeupMainFunction wakeup_main_function,
04996 void *data,
04997 DBusFreeFunction free_data_function)
04998 {
04999 void *old_data;
05000 DBusFreeFunction old_free_data;
05001
05002 _dbus_return_if_fail (connection != NULL);
05003
05004 CONNECTION_LOCK (connection);
05005 old_data = connection->wakeup_main_data;
05006 old_free_data = connection->free_wakeup_main_data;
05007
05008 connection->wakeup_main_function = wakeup_main_function;
05009 connection->wakeup_main_data = data;
05010 connection->free_wakeup_main_data = free_data_function;
05011
05012 CONNECTION_UNLOCK (connection);
05013
05014
05015 if (old_free_data)
05016 (*old_free_data) (old_data);
05017 }
05018
05039 void
05040 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
05041 DBusDispatchStatusFunction function,
05042 void *data,
05043 DBusFreeFunction free_data_function)
05044 {
05045 void *old_data;
05046 DBusFreeFunction old_free_data;
05047
05048 _dbus_return_if_fail (connection != NULL);
05049
05050 CONNECTION_LOCK (connection);
05051 old_data = connection->dispatch_status_data;
05052 old_free_data = connection->free_dispatch_status_data;
05053
05054 connection->dispatch_status_function = function;
05055 connection->dispatch_status_data = data;
05056 connection->free_dispatch_status_data = free_data_function;
05057
05058 CONNECTION_UNLOCK (connection);
05059
05060
05061 if (old_free_data)
05062 (*old_free_data) (old_data);
05063 }
05064
05084 dbus_bool_t
05085 dbus_connection_get_unix_fd (DBusConnection *connection,
05086 int *fd)
05087 {
05088 _dbus_return_val_if_fail (connection != NULL, FALSE);
05089 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05090
05091 #ifdef DBUS_WIN
05092
05093 return FALSE;
05094 #endif
05095
05096 return dbus_connection_get_socket(connection, fd);
05097 }
05098
05114 dbus_bool_t
05115 dbus_connection_get_socket(DBusConnection *connection,
05116 int *fd)
05117 {
05118 dbus_bool_t retval;
05119
05120 _dbus_return_val_if_fail (connection != NULL, FALSE);
05121 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05122
05123 CONNECTION_LOCK (connection);
05124
05125 retval = _dbus_transport_get_socket_fd (connection->transport,
05126 fd);
05127
05128 CONNECTION_UNLOCK (connection);
05129
05130 return retval;
05131 }
05132
05133
05156 dbus_bool_t
05157 dbus_connection_get_unix_user (DBusConnection *connection,
05158 unsigned long *uid)
05159 {
05160 dbus_bool_t result;
05161
05162 _dbus_return_val_if_fail (connection != NULL, FALSE);
05163 _dbus_return_val_if_fail (uid != NULL, FALSE);
05164
05165 CONNECTION_LOCK (connection);
05166
05167 if (!_dbus_transport_get_is_authenticated (connection->transport))
05168 result = FALSE;
05169 else
05170 result = _dbus_transport_get_unix_user (connection->transport,
05171 uid);
05172
05173 #ifdef DBUS_WIN
05174 _dbus_assert (!result);
05175 #endif
05176
05177 CONNECTION_UNLOCK (connection);
05178
05179 return result;
05180 }
05181
05192 dbus_bool_t
05193 dbus_connection_get_unix_process_id (DBusConnection *connection,
05194 unsigned long *pid)
05195 {
05196 dbus_bool_t result;
05197
05198 _dbus_return_val_if_fail (connection != NULL, FALSE);
05199 _dbus_return_val_if_fail (pid != NULL, FALSE);
05200
05201 CONNECTION_LOCK (connection);
05202
05203 if (!_dbus_transport_get_is_authenticated (connection->transport))
05204 result = FALSE;
05205 else
05206 result = _dbus_transport_get_unix_process_id (connection->transport,
05207 pid);
05208
05209 CONNECTION_UNLOCK (connection);
05210
05211 return result;
05212 }
05213
05224 dbus_bool_t
05225 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05226 void **data,
05227 dbus_int32_t *data_size)
05228 {
05229 dbus_bool_t result;
05230
05231 _dbus_return_val_if_fail (connection != NULL, FALSE);
05232 _dbus_return_val_if_fail (data != NULL, FALSE);
05233 _dbus_return_val_if_fail (data_size != NULL, FALSE);
05234
05235 CONNECTION_LOCK (connection);
05236
05237 if (!_dbus_transport_get_is_authenticated (connection->transport))
05238 result = FALSE;
05239 else
05240 result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05241 data,
05242 data_size);
05243 CONNECTION_UNLOCK (connection);
05244
05245 return result;
05246 }
05247
05270 void
05271 dbus_connection_set_unix_user_function (DBusConnection *connection,
05272 DBusAllowUnixUserFunction function,
05273 void *data,
05274 DBusFreeFunction free_data_function)
05275 {
05276 void *old_data = NULL;
05277 DBusFreeFunction old_free_function = NULL;
05278
05279 _dbus_return_if_fail (connection != NULL);
05280
05281 CONNECTION_LOCK (connection);
05282 _dbus_transport_set_unix_user_function (connection->transport,
05283 function, data, free_data_function,
05284 &old_data, &old_free_function);
05285 CONNECTION_UNLOCK (connection);
05286
05287 if (old_free_function != NULL)
05288 (* old_free_function) (old_data);
05289 }
05290
05322 dbus_bool_t
05323 dbus_connection_get_windows_user (DBusConnection *connection,
05324 char **windows_sid_p)
05325 {
05326 dbus_bool_t result;
05327
05328 _dbus_return_val_if_fail (connection != NULL, FALSE);
05329 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05330
05331 CONNECTION_LOCK (connection);
05332
05333 if (!_dbus_transport_get_is_authenticated (connection->transport))
05334 result = FALSE;
05335 else
05336 result = _dbus_transport_get_windows_user (connection->transport,
05337 windows_sid_p);
05338
05339 #ifdef DBUS_UNIX
05340 _dbus_assert (!result);
05341 #endif
05342
05343 CONNECTION_UNLOCK (connection);
05344
05345 return result;
05346 }
05347
05369 void
05370 dbus_connection_set_windows_user_function (DBusConnection *connection,
05371 DBusAllowWindowsUserFunction function,
05372 void *data,
05373 DBusFreeFunction free_data_function)
05374 {
05375 void *old_data = NULL;
05376 DBusFreeFunction old_free_function = NULL;
05377
05378 _dbus_return_if_fail (connection != NULL);
05379
05380 CONNECTION_LOCK (connection);
05381 _dbus_transport_set_windows_user_function (connection->transport,
05382 function, data, free_data_function,
05383 &old_data, &old_free_function);
05384 CONNECTION_UNLOCK (connection);
05385
05386 if (old_free_function != NULL)
05387 (* old_free_function) (old_data);
05388 }
05389
05416 void
05417 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05418 dbus_bool_t value)
05419 {
05420 _dbus_return_if_fail (connection != NULL);
05421
05422 CONNECTION_LOCK (connection);
05423 _dbus_transport_set_allow_anonymous (connection->transport, value);
05424 CONNECTION_UNLOCK (connection);
05425 }
05426
05444 void
05445 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05446 dbus_bool_t value)
05447 {
05448 _dbus_return_if_fail (connection != NULL);
05449
05450 CONNECTION_LOCK (connection);
05451 connection->route_peer_messages = TRUE;
05452 CONNECTION_UNLOCK (connection);
05453 }
05454
05476 dbus_bool_t
05477 dbus_connection_add_filter (DBusConnection *connection,
05478 DBusHandleMessageFunction function,
05479 void *user_data,
05480 DBusFreeFunction free_data_function)
05481 {
05482 DBusMessageFilter *filter;
05483
05484 _dbus_return_val_if_fail (connection != NULL, FALSE);
05485 _dbus_return_val_if_fail (function != NULL, FALSE);
05486
05487 filter = dbus_new0 (DBusMessageFilter, 1);
05488 if (filter == NULL)
05489 return FALSE;
05490
05491 filter->refcount.value = 1;
05492
05493 CONNECTION_LOCK (connection);
05494
05495 if (!_dbus_list_append (&connection->filter_list,
05496 filter))
05497 {
05498 _dbus_message_filter_unref (filter);
05499 CONNECTION_UNLOCK (connection);
05500 return FALSE;
05501 }
05502
05503
05504
05505
05506
05507
05508 filter->function = function;
05509 filter->user_data = user_data;
05510 filter->free_user_data_function = free_data_function;
05511
05512 CONNECTION_UNLOCK (connection);
05513 return TRUE;
05514 }
05515
05528 void
05529 dbus_connection_remove_filter (DBusConnection *connection,
05530 DBusHandleMessageFunction function,
05531 void *user_data)
05532 {
05533 DBusList *link;
05534 DBusMessageFilter *filter;
05535
05536 _dbus_return_if_fail (connection != NULL);
05537 _dbus_return_if_fail (function != NULL);
05538
05539 CONNECTION_LOCK (connection);
05540
05541 filter = NULL;
05542
05543 link = _dbus_list_get_last_link (&connection->filter_list);
05544 while (link != NULL)
05545 {
05546 filter = link->data;
05547
05548 if (filter->function == function &&
05549 filter->user_data == user_data)
05550 {
05551 _dbus_list_remove_link (&connection->filter_list, link);
05552 filter->function = NULL;
05553
05554 break;
05555 }
05556
05557 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05558 filter = NULL;
05559 }
05560
05561 CONNECTION_UNLOCK (connection);
05562
05563 #ifndef DBUS_DISABLE_CHECKS
05564 if (filter == NULL)
05565 {
05566 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05567 function, user_data);
05568 return;
05569 }
05570 #endif
05571
05572
05573 if (filter->free_user_data_function)
05574 (* filter->free_user_data_function) (filter->user_data);
05575
05576 filter->free_user_data_function = NULL;
05577 filter->user_data = NULL;
05578
05579 _dbus_message_filter_unref (filter);
05580 }
05581
05594 dbus_bool_t
05595 dbus_connection_try_register_object_path (DBusConnection *connection,
05596 const char *path,
05597 const DBusObjectPathVTable *vtable,
05598 void *user_data,
05599 DBusError *error)
05600 {
05601 char **decomposed_path;
05602 dbus_bool_t retval;
05603
05604 _dbus_return_val_if_fail (connection != NULL, FALSE);
05605 _dbus_return_val_if_fail (path != NULL, FALSE);
05606 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05607 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05608
05609 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05610 return FALSE;
05611
05612 CONNECTION_LOCK (connection);
05613
05614 retval = _dbus_object_tree_register (connection->objects,
05615 FALSE,
05616 (const char **) decomposed_path, vtable,
05617 user_data, error);
05618
05619 CONNECTION_UNLOCK (connection);
05620
05621 dbus_free_string_array (decomposed_path);
05622
05623 return retval;
05624 }
05625
05640 dbus_bool_t
05641 dbus_connection_register_object_path (DBusConnection *connection,
05642 const char *path,
05643 const DBusObjectPathVTable *vtable,
05644 void *user_data)
05645 {
05646 char **decomposed_path;
05647 dbus_bool_t retval;
05648 DBusError error = DBUS_ERROR_INIT;
05649
05650 _dbus_return_val_if_fail (connection != NULL, FALSE);
05651 _dbus_return_val_if_fail (path != NULL, FALSE);
05652 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05653 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05654
05655 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05656 return FALSE;
05657
05658 CONNECTION_LOCK (connection);
05659
05660 retval = _dbus_object_tree_register (connection->objects,
05661 FALSE,
05662 (const char **) decomposed_path, vtable,
05663 user_data, &error);
05664
05665 CONNECTION_UNLOCK (connection);
05666
05667 dbus_free_string_array (decomposed_path);
05668
05669 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05670 {
05671 _dbus_warn ("%s\n", error.message);
05672 dbus_error_free (&error);
05673 return FALSE;
05674 }
05675
05676 return retval;
05677 }
05678
05693 dbus_bool_t
05694 dbus_connection_try_register_fallback (DBusConnection *connection,
05695 const char *path,
05696 const DBusObjectPathVTable *vtable,
05697 void *user_data,
05698 DBusError *error)
05699 {
05700 char **decomposed_path;
05701 dbus_bool_t retval;
05702
05703 _dbus_return_val_if_fail (connection != NULL, FALSE);
05704 _dbus_return_val_if_fail (path != NULL, FALSE);
05705 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05706 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05707
05708 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05709 return FALSE;
05710
05711 CONNECTION_LOCK (connection);
05712
05713 retval = _dbus_object_tree_register (connection->objects,
05714 TRUE,
05715 (const char **) decomposed_path, vtable,
05716 user_data, error);
05717
05718 CONNECTION_UNLOCK (connection);
05719
05720 dbus_free_string_array (decomposed_path);
05721
05722 return retval;
05723 }
05724
05741 dbus_bool_t
05742 dbus_connection_register_fallback (DBusConnection *connection,
05743 const char *path,
05744 const DBusObjectPathVTable *vtable,
05745 void *user_data)
05746 {
05747 char **decomposed_path;
05748 dbus_bool_t retval;
05749 DBusError error = DBUS_ERROR_INIT;
05750
05751 _dbus_return_val_if_fail (connection != NULL, FALSE);
05752 _dbus_return_val_if_fail (path != NULL, FALSE);
05753 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05754 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05755
05756 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05757 return FALSE;
05758
05759 CONNECTION_LOCK (connection);
05760
05761 retval = _dbus_object_tree_register (connection->objects,
05762 TRUE,
05763 (const char **) decomposed_path, vtable,
05764 user_data, &error);
05765
05766 CONNECTION_UNLOCK (connection);
05767
05768 dbus_free_string_array (decomposed_path);
05769
05770 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05771 {
05772 _dbus_warn ("%s\n", error.message);
05773 dbus_error_free (&error);
05774 return FALSE;
05775 }
05776
05777 return retval;
05778 }
05779
05789 dbus_bool_t
05790 dbus_connection_unregister_object_path (DBusConnection *connection,
05791 const char *path)
05792 {
05793 char **decomposed_path;
05794
05795 _dbus_return_val_if_fail (connection != NULL, FALSE);
05796 _dbus_return_val_if_fail (path != NULL, FALSE);
05797 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05798
05799 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05800 return FALSE;
05801
05802 CONNECTION_LOCK (connection);
05803
05804 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05805
05806 dbus_free_string_array (decomposed_path);
05807
05808 return TRUE;
05809 }
05810
05821 dbus_bool_t
05822 dbus_connection_get_object_path_data (DBusConnection *connection,
05823 const char *path,
05824 void **data_p)
05825 {
05826 char **decomposed_path;
05827
05828 _dbus_return_val_if_fail (connection != NULL, FALSE);
05829 _dbus_return_val_if_fail (path != NULL, FALSE);
05830 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05831
05832 *data_p = NULL;
05833
05834 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05835 return FALSE;
05836
05837 CONNECTION_LOCK (connection);
05838
05839 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05840
05841 CONNECTION_UNLOCK (connection);
05842
05843 dbus_free_string_array (decomposed_path);
05844
05845 return TRUE;
05846 }
05847
05858 dbus_bool_t
05859 dbus_connection_list_registered (DBusConnection *connection,
05860 const char *parent_path,
05861 char ***child_entries)
05862 {
05863 char **decomposed_path;
05864 dbus_bool_t retval;
05865 _dbus_return_val_if_fail (connection != NULL, FALSE);
05866 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05867 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05868 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05869
05870 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05871 return FALSE;
05872
05873 CONNECTION_LOCK (connection);
05874
05875 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05876 (const char **) decomposed_path,
05877 child_entries);
05878 dbus_free_string_array (decomposed_path);
05879
05880 return retval;
05881 }
05882
05883 static DBusDataSlotAllocator slot_allocator;
05884 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05885
05900 dbus_bool_t
05901 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05902 {
05903 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05904 &_DBUS_LOCK_NAME (connection_slots),
05905 slot_p);
05906 }
05907
05919 void
05920 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05921 {
05922 _dbus_return_if_fail (*slot_p >= 0);
05923
05924 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05925 }
05926
05949 dbus_bool_t
05950 dbus_connection_set_data (DBusConnection *connection,
05951 dbus_int32_t slot,
05952 void *data,
05953 DBusFreeFunction free_data_func)
05954 {
05955 DBusFreeFunction old_free_func;
05956 void *old_data;
05957 dbus_bool_t retval;
05958
05959 _dbus_return_val_if_fail (connection != NULL, FALSE);
05960 _dbus_return_val_if_fail (slot >= 0, FALSE);
05961
05962 SLOTS_LOCK (connection);
05963
05964 retval = _dbus_data_slot_list_set (&slot_allocator,
05965 &connection->slot_list,
05966 slot, data, free_data_func,
05967 &old_free_func, &old_data);
05968
05969 SLOTS_UNLOCK (connection);
05970
05971 if (retval)
05972 {
05973
05974 if (old_free_func)
05975 (* old_free_func) (old_data);
05976 }
05977
05978 return retval;
05979 }
05980
05998 void*
05999 dbus_connection_get_data (DBusConnection *connection,
06000 dbus_int32_t slot)
06001 {
06002 void *res;
06003
06004 _dbus_return_val_if_fail (connection != NULL, NULL);
06005
06006 SLOTS_LOCK (connection);
06007
06008 res = _dbus_data_slot_list_get (&slot_allocator,
06009 &connection->slot_list,
06010 slot);
06011
06012 SLOTS_UNLOCK (connection);
06013
06014 return res;
06015 }
06016
06023 void
06024 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
06025 {
06026 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
06027 }
06028
06037 void
06038 dbus_connection_set_max_message_size (DBusConnection *connection,
06039 long size)
06040 {
06041 _dbus_return_if_fail (connection != NULL);
06042
06043 CONNECTION_LOCK (connection);
06044 _dbus_transport_set_max_message_size (connection->transport,
06045 size);
06046 CONNECTION_UNLOCK (connection);
06047 }
06048
06055 long
06056 dbus_connection_get_max_message_size (DBusConnection *connection)
06057 {
06058 long res;
06059
06060 _dbus_return_val_if_fail (connection != NULL, 0);
06061
06062 CONNECTION_LOCK (connection);
06063 res = _dbus_transport_get_max_message_size (connection->transport);
06064 CONNECTION_UNLOCK (connection);
06065 return res;
06066 }
06067
06076 void
06077 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06078 long n)
06079 {
06080 _dbus_return_if_fail (connection != NULL);
06081
06082 CONNECTION_LOCK (connection);
06083 _dbus_transport_set_max_message_unix_fds (connection->transport,
06084 n);
06085 CONNECTION_UNLOCK (connection);
06086 }
06087
06094 long
06095 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06096 {
06097 long res;
06098
06099 _dbus_return_val_if_fail (connection != NULL, 0);
06100
06101 CONNECTION_LOCK (connection);
06102 res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06103 CONNECTION_UNLOCK (connection);
06104 return res;
06105 }
06106
06132 void
06133 dbus_connection_set_max_received_size (DBusConnection *connection,
06134 long size)
06135 {
06136 _dbus_return_if_fail (connection != NULL);
06137
06138 CONNECTION_LOCK (connection);
06139 _dbus_transport_set_max_received_size (connection->transport,
06140 size);
06141 CONNECTION_UNLOCK (connection);
06142 }
06143
06150 long
06151 dbus_connection_get_max_received_size (DBusConnection *connection)
06152 {
06153 long res;
06154
06155 _dbus_return_val_if_fail (connection != NULL, 0);
06156
06157 CONNECTION_LOCK (connection);
06158 res = _dbus_transport_get_max_received_size (connection->transport);
06159 CONNECTION_UNLOCK (connection);
06160 return res;
06161 }
06162
06174 void
06175 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06176 long n)
06177 {
06178 _dbus_return_if_fail (connection != NULL);
06179
06180 CONNECTION_LOCK (connection);
06181 _dbus_transport_set_max_received_unix_fds (connection->transport,
06182 n);
06183 CONNECTION_UNLOCK (connection);
06184 }
06185
06192 long
06193 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06194 {
06195 long res;
06196
06197 _dbus_return_val_if_fail (connection != NULL, 0);
06198
06199 CONNECTION_LOCK (connection);
06200 res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06201 CONNECTION_UNLOCK (connection);
06202 return res;
06203 }
06204
06215 long
06216 dbus_connection_get_outgoing_size (DBusConnection *connection)
06217 {
06218 long res;
06219
06220 _dbus_return_val_if_fail (connection != NULL, 0);
06221
06222 CONNECTION_LOCK (connection);
06223 res = _dbus_counter_get_size_value (connection->outgoing_counter);
06224 CONNECTION_UNLOCK (connection);
06225 return res;
06226 }
06227
06235 long
06236 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06237 {
06238 long res;
06239
06240 _dbus_return_val_if_fail (connection != NULL, 0);
06241
06242 CONNECTION_LOCK (connection);
06243 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06244 CONNECTION_UNLOCK (connection);
06245 return res;
06246 }
06247