D-Bus 1.12.20
dbus-connection.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-connection.c DBusConnection object
3 *
4 * Copyright (C) 2002-2006 Red Hat Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24#include <config.h>
25#include "dbus-shared.h"
26#include "dbus-connection.h"
27#include "dbus-list.h"
28#include "dbus-timeout.h"
29#include "dbus-transport.h"
30#include "dbus-watch.h"
31#include "dbus-connection-internal.h"
32#include "dbus-pending-call-internal.h"
33#include "dbus-list.h"
34#include "dbus-hash.h"
35#include "dbus-message-internal.h"
36#include "dbus-message-private.h"
37#include "dbus-threads.h"
38#include "dbus-protocol.h"
39#include "dbus-dataslot.h"
40#include "dbus-string.h"
41#include "dbus-signature.h"
42#include "dbus-pending-call.h"
43#include "dbus-object-tree.h"
44#include "dbus-threads-internal.h"
45#include "dbus-bus.h"
46#include "dbus-marshal-basic.h"
47
48#ifdef DBUS_DISABLE_CHECKS
49#define TOOK_LOCK_CHECK(connection)
50#define RELEASING_LOCK_CHECK(connection)
51#define HAVE_LOCK_CHECK(connection)
52#else
53#define TOOK_LOCK_CHECK(connection) do { \
54 _dbus_assert (!(connection)->have_connection_lock); \
55 (connection)->have_connection_lock = TRUE; \
56 } while (0)
57#define RELEASING_LOCK_CHECK(connection) do { \
58 _dbus_assert ((connection)->have_connection_lock); \
59 (connection)->have_connection_lock = FALSE; \
60 } while (0)
61#define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
62/* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
63#endif
64
65#define TRACE_LOCKS 1
66
67#define CONNECTION_LOCK(connection) do { \
68 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
69 _dbus_rmutex_lock ((connection)->mutex); \
70 TOOK_LOCK_CHECK (connection); \
71 } while (0)
72
73#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
74
75#define SLOTS_LOCK(connection) do { \
76 _dbus_rmutex_lock ((connection)->slot_mutex); \
77 } while (0)
78
79#define SLOTS_UNLOCK(connection) do { \
80 _dbus_rmutex_unlock ((connection)->slot_mutex); \
81 } while (0)
82
83#define DISPATCH_STATUS_NAME(s) \
84 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
85 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
86 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
87 "???")
88
206static void
207_dbus_connection_trace_ref (DBusConnection *connection,
208 int old_refcount,
209 int new_refcount,
210 const char *why)
211{
212#ifdef DBUS_ENABLE_VERBOSE_MODE
213 static int enabled = -1;
214
215 _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
216 why, "DBUS_CONNECTION_TRACE", &enabled);
217#endif
218}
219
224
229{
232 void *user_data;
234};
235
236
241{
245};
246
247#if HAVE_DECL_MSG_NOSIGNAL
248static dbus_bool_t _dbus_modify_sigpipe = FALSE;
249#else
250static dbus_bool_t _dbus_modify_sigpipe = TRUE;
251#endif
252
257{
308 /* These two MUST be bools and not bitfields, because they are protected by a separate lock
309 * from connection->mutex and all bitfields in a word have to be read/written together.
310 * So you can't have a different lock for different bitfields in the same word.
311 */
315 unsigned int shareable : 1;
317 unsigned int exit_on_disconnect : 1;
319 unsigned int route_peer_messages : 1;
329#ifndef DBUS_DISABLE_CHECKS
330 unsigned int have_connection_lock : 1;
331#endif
332
333#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
334 int generation;
335#endif
336};
337
338static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
339static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
340 DBusDispatchStatus new_status);
341static void _dbus_connection_last_unref (DBusConnection *connection);
342static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
343static void _dbus_connection_release_dispatch (DBusConnection *connection);
344static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
345static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
346static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
347static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
348 dbus_uint32_t client_serial);
349
350static DBusMessageFilter *
351_dbus_message_filter_ref (DBusMessageFilter *filter)
352{
353#ifdef DBUS_DISABLE_ASSERT
354 _dbus_atomic_inc (&filter->refcount);
355#else
356 dbus_int32_t old_value;
357
358 old_value = _dbus_atomic_inc (&filter->refcount);
359 _dbus_assert (old_value > 0);
360#endif
361
362 return filter;
363}
364
365static void
366_dbus_message_filter_unref (DBusMessageFilter *filter)
367{
368 dbus_int32_t old_value;
369
370 old_value = _dbus_atomic_dec (&filter->refcount);
371 _dbus_assert (old_value > 0);
372
373 if (old_value == 1)
374 {
375 if (filter->free_user_data_function)
376 (* filter->free_user_data_function) (filter->user_data);
377
378 dbus_free (filter);
379 }
380}
381
387void
389{
390 CONNECTION_LOCK (connection);
391}
392
398void
400{
401 DBusList *expired_messages;
402 DBusList *iter;
403
404 if (TRACE_LOCKS)
405 {
406 _dbus_verbose ("UNLOCK\n");
407 }
408
409 /* If we had messages that expired (fell off the incoming or outgoing
410 * queues) while we were locked, actually release them now */
411 expired_messages = connection->expired_messages;
412 connection->expired_messages = NULL;
413
414 RELEASING_LOCK_CHECK (connection);
415 _dbus_rmutex_unlock (connection->mutex);
416
417 for (iter = _dbus_list_pop_first_link (&expired_messages);
418 iter != NULL;
419 iter = _dbus_list_pop_first_link (&expired_messages))
420 {
421 DBusMessage *message = iter->data;
422
423 dbus_message_unref (message);
425 }
426}
427
435static void
436_dbus_connection_wakeup_mainloop (DBusConnection *connection)
437{
438 if (connection->wakeup_main_function)
439 (*connection->wakeup_main_function) (connection->wakeup_main_data);
440}
441
442#ifdef DBUS_ENABLE_EMBEDDED_TESTS
455void
456_dbus_connection_test_get_locks (DBusConnection *connection,
457 DBusMutex **mutex_loc,
458 DBusMutex **dispatch_mutex_loc,
459 DBusMutex **io_path_mutex_loc,
460 DBusCondVar **dispatch_cond_loc,
461 DBusCondVar **io_path_cond_loc)
462{
463 *mutex_loc = (DBusMutex *) connection->mutex;
464 *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
465 *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
466 *dispatch_cond_loc = connection->dispatch_cond;
467 *io_path_cond_loc = connection->io_path_cond;
468}
469#endif
470
479void
481 DBusList *link)
482{
483 DBusPendingCall *pending;
484 dbus_uint32_t reply_serial;
485 DBusMessage *message;
486
488
490 link);
491 message = link->data;
492
493 /* If this is a reply we're waiting on, remove timeout for it */
494 reply_serial = dbus_message_get_reply_serial (message);
495 if (reply_serial != 0)
496 {
497 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
498 reply_serial);
499 if (pending != NULL)
500 {
504
506 }
507 }
508
509
510
511 connection->n_incoming += 1;
512
513 _dbus_connection_wakeup_mainloop (connection);
514
515 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
516 message,
518 dbus_message_get_path (message) ?
519 dbus_message_get_path (message) :
520 "no path",
523 "no interface",
524 dbus_message_get_member (message) ?
525 dbus_message_get_member (message) :
526 "no member",
529 connection,
530 connection->n_incoming);
531
532 _dbus_message_trace_ref (message, -1, -1,
533 "_dbus_conection_queue_received_message_link");
534}
535
544void
546 DBusList *link)
547{
548 HAVE_LOCK_CHECK (connection);
549
550 _dbus_list_append_link (&connection->incoming_messages, link);
551
552 connection->n_incoming += 1;
553
554 _dbus_connection_wakeup_mainloop (connection);
555
556 _dbus_message_trace_ref (link->data, -1, -1,
557 "_dbus_connection_queue_synthesized_message_link");
558
559 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
560 link->data, connection, connection->n_incoming);
561}
562
563
573{
574 HAVE_LOCK_CHECK (connection);
575 return connection->outgoing_messages != NULL;
576}
577
589{
590 dbus_bool_t v;
591
592 _dbus_return_val_if_fail (connection != NULL, FALSE);
593
594 CONNECTION_LOCK (connection);
596 CONNECTION_UNLOCK (connection);
597
598 return v;
599}
600
610{
611 HAVE_LOCK_CHECK (connection);
612
613 return _dbus_list_get_last (&connection->outgoing_messages);
614}
615
624void
626 DBusMessage *message)
627{
628 DBusList *link;
629
630 HAVE_LOCK_CHECK (connection);
631
632 /* This can be called before we even complete authentication, since
633 * it's called on disconnect to clean up the outgoing queue.
634 * It's also called as we successfully send each message.
635 */
636
637 link = _dbus_list_get_last_link (&connection->outgoing_messages);
638 _dbus_assert (link != NULL);
639 _dbus_assert (link->data == message);
640
642 link);
643 _dbus_list_prepend_link (&connection->expired_messages, link);
644
645 connection->n_outgoing -= 1;
646
647 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
648 message,
650 dbus_message_get_path (message) ?
651 dbus_message_get_path (message) :
652 "no path",
655 "no interface",
656 dbus_message_get_member (message) ?
657 dbus_message_get_member (message) :
658 "no member",
660 connection, connection->n_outgoing);
661
662 /* It's OK that in principle we call the notify function, because for the
663 * outgoing limit, there isn't one */
664 _dbus_message_remove_counter (message, connection->outgoing_counter);
665
666 /* The message will actually be unreffed when we unlock */
667}
668
671 DBusWatch *watch);
674 DBusWatch *watch);
677 DBusWatch *watch,
678 dbus_bool_t enabled);
679
680static dbus_bool_t
681protected_change_watch (DBusConnection *connection,
682 DBusWatch *watch,
683 DBusWatchAddFunction add_function,
684 DBusWatchRemoveFunction remove_function,
685 DBusWatchToggleFunction toggle_function,
686 dbus_bool_t enabled)
687{
688 dbus_bool_t retval;
689
690 HAVE_LOCK_CHECK (connection);
691
692 /* The original purpose of protected_change_watch() was to hold a
693 * ref on the connection while dropping the connection lock, then
694 * calling out to the app. This was a broken hack that did not
695 * work, since the connection was in a hosed state (no WatchList
696 * field) while calling out.
697 *
698 * So for now we'll just keep the lock while calling out. This means
699 * apps are not allowed to call DBusConnection methods inside a
700 * watch function or they will deadlock.
701 *
702 * The "real fix" is to use the _and_unlock() pattern found
703 * elsewhere in the code, to defer calling out to the app until
704 * we're about to drop locks and return flow of control to the app
705 * anyway.
706 *
707 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
708 */
709
710 if (connection->watches)
711 {
712 if (add_function)
713 retval = (* add_function) (connection->watches, watch);
714 else if (remove_function)
715 {
716 retval = TRUE;
717 (* remove_function) (connection->watches, watch);
718 }
719 else
720 {
721 retval = TRUE;
722 (* toggle_function) (connection->watches, watch, enabled);
723 }
724 return retval;
725 }
726 else
727 return FALSE;
728}
729
730
744 DBusWatch *watch)
745{
746 return protected_change_watch (connection, watch,
748 NULL, NULL, FALSE);
749}
750
760void
762 DBusWatch *watch)
763{
764 protected_change_watch (connection, watch,
765 NULL,
767 NULL, FALSE);
768}
769
780void
782 DBusWatch *watch,
783 dbus_bool_t enabled)
784{
785 _dbus_assert (watch != NULL);
786
787 protected_change_watch (connection, watch,
788 NULL, NULL,
790 enabled);
791}
792
795 DBusTimeout *timeout);
798 DBusTimeout *timeout);
801 DBusTimeout *timeout,
802 dbus_bool_t enabled);
803
804static dbus_bool_t
805protected_change_timeout (DBusConnection *connection,
806 DBusTimeout *timeout,
807 DBusTimeoutAddFunction add_function,
808 DBusTimeoutRemoveFunction remove_function,
809 DBusTimeoutToggleFunction toggle_function,
810 dbus_bool_t enabled)
811{
812 dbus_bool_t retval;
813
814 HAVE_LOCK_CHECK (connection);
815
816 /* The original purpose of protected_change_timeout() was to hold a
817 * ref on the connection while dropping the connection lock, then
818 * calling out to the app. This was a broken hack that did not
819 * work, since the connection was in a hosed state (no TimeoutList
820 * field) while calling out.
821 *
822 * So for now we'll just keep the lock while calling out. This means
823 * apps are not allowed to call DBusConnection methods inside a
824 * timeout function or they will deadlock.
825 *
826 * The "real fix" is to use the _and_unlock() pattern found
827 * elsewhere in the code, to defer calling out to the app until
828 * we're about to drop locks and return flow of control to the app
829 * anyway.
830 *
831 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
832 */
833
834 if (connection->timeouts)
835 {
836 if (add_function)
837 retval = (* add_function) (connection->timeouts, timeout);
838 else if (remove_function)
839 {
840 retval = TRUE;
841 (* remove_function) (connection->timeouts, timeout);
842 }
843 else
844 {
845 retval = TRUE;
846 (* toggle_function) (connection->timeouts, timeout, enabled);
847 }
848 return retval;
849 }
850 else
851 return FALSE;
852}
853
868 DBusTimeout *timeout)
869{
870 return protected_change_timeout (connection, timeout,
872 NULL, NULL, FALSE);
873}
874
884void
886 DBusTimeout *timeout)
887{
888 protected_change_timeout (connection, timeout,
889 NULL,
891 NULL, FALSE);
892}
893
904void
906 DBusTimeout *timeout,
907 dbus_bool_t enabled)
908{
909 protected_change_timeout (connection, timeout,
910 NULL, NULL,
912 enabled);
913}
914
915static dbus_bool_t
916_dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
917 DBusPendingCall *pending)
918{
919 dbus_uint32_t reply_serial;
920 DBusTimeout *timeout;
921
922 HAVE_LOCK_CHECK (connection);
923
924 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
925
926 _dbus_assert (reply_serial != 0);
927
928 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
929
930 if (timeout)
931 {
932 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
933 return FALSE;
934
936 reply_serial,
937 pending))
938 {
939 _dbus_connection_remove_timeout_unlocked (connection, timeout);
940
942 HAVE_LOCK_CHECK (connection);
943 return FALSE;
944 }
945
947 }
948 else
949 {
951 reply_serial,
952 pending))
953 {
954 HAVE_LOCK_CHECK (connection);
955 return FALSE;
956 }
957 }
958
960
961 HAVE_LOCK_CHECK (connection);
962
963 return TRUE;
964}
965
966static void
967free_pending_call_on_hash_removal (void *data)
968{
969 DBusPendingCall *pending;
970 DBusConnection *connection;
971
972 if (data == NULL)
973 return;
974
975 pending = data;
976
977 connection = _dbus_pending_call_get_connection_unlocked (pending);
978
979 HAVE_LOCK_CHECK (connection);
980
982 {
985
987 }
988
989 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock
990 * here, but the pending call finalizer could in principle call out to
991 * application code so we pretty much have to... some larger code reorg
992 * might be needed.
993 */
996 CONNECTION_LOCK (connection);
998}
999
1000static void
1001_dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
1002 DBusPendingCall *pending)
1003{
1004 /* This ends up unlocking to call the pending call finalizer, which is unexpected to
1005 * say the least.
1006 */
1009}
1010
1011static void
1012_dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
1013 DBusPendingCall *pending)
1014{
1015 /* The idea here is to avoid finalizing the pending call
1016 * with the lock held, since there's a destroy notifier
1017 * in pending call that goes out to application code.
1018 *
1019 * There's an extra unlock inside the hash table
1020 * "free pending call" function FIXME...
1021 */
1025
1029
1031
1033}
1034
1043void
1045 DBusPendingCall *pending)
1046{
1047 CONNECTION_LOCK (connection);
1048 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
1049}
1050
1060static dbus_bool_t
1061_dbus_connection_acquire_io_path (DBusConnection *connection,
1062 int timeout_milliseconds)
1063{
1064 dbus_bool_t we_acquired;
1065
1066 HAVE_LOCK_CHECK (connection);
1067
1068 /* We don't want the connection to vanish */
1069 _dbus_connection_ref_unlocked (connection);
1070
1071 /* We will only touch io_path_acquired which is protected by our mutex */
1072 CONNECTION_UNLOCK (connection);
1073
1074 _dbus_verbose ("locking io_path_mutex\n");
1075 _dbus_cmutex_lock (connection->io_path_mutex);
1076
1077 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
1078 connection->io_path_acquired, timeout_milliseconds);
1079
1080 we_acquired = FALSE;
1081
1082 if (connection->io_path_acquired)
1083 {
1084 if (timeout_milliseconds != -1)
1085 {
1086 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
1087 timeout_milliseconds);
1088
1089 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
1090 connection->io_path_mutex,
1091 timeout_milliseconds))
1092 {
1093 /* We timed out before anyone signaled. */
1094 /* (writing the loop to handle the !timedout case by
1095 * waiting longer if needed is a pain since dbus
1096 * wraps pthread_cond_timedwait to take a relative
1097 * time instead of absolute, something kind of stupid
1098 * on our part. for now it doesn't matter, we will just
1099 * end up back here eventually.)
1100 */
1101 }
1102 }
1103 else
1104 {
1105 while (connection->io_path_acquired)
1106 {
1107 _dbus_verbose ("waiting for IO path to be acquirable\n");
1108 _dbus_condvar_wait (connection->io_path_cond,
1109 connection->io_path_mutex);
1110 }
1111 }
1112 }
1113
1114 if (!connection->io_path_acquired)
1115 {
1116 we_acquired = TRUE;
1117 connection->io_path_acquired = TRUE;
1118 }
1119
1120 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
1121 connection->io_path_acquired, we_acquired);
1122
1123 _dbus_verbose ("unlocking io_path_mutex\n");
1124 _dbus_cmutex_unlock (connection->io_path_mutex);
1125
1126 CONNECTION_LOCK (connection);
1127
1128 HAVE_LOCK_CHECK (connection);
1129
1131
1132 return we_acquired;
1133}
1134
1142static void
1143_dbus_connection_release_io_path (DBusConnection *connection)
1144{
1145 HAVE_LOCK_CHECK (connection);
1146
1147 _dbus_verbose ("locking io_path_mutex\n");
1148 _dbus_cmutex_lock (connection->io_path_mutex);
1149
1150 _dbus_assert (connection->io_path_acquired);
1151
1152 _dbus_verbose ("start connection->io_path_acquired = %d\n",
1153 connection->io_path_acquired);
1154
1155 connection->io_path_acquired = FALSE;
1157
1158 _dbus_verbose ("unlocking io_path_mutex\n");
1159 _dbus_cmutex_unlock (connection->io_path_mutex);
1160}
1161
1197void
1199 DBusPendingCall *pending,
1200 unsigned int flags,
1201 int timeout_milliseconds)
1202{
1203 _dbus_verbose ("start\n");
1204
1205 HAVE_LOCK_CHECK (connection);
1206
1207 if (connection->n_outgoing == 0)
1208 flags &= ~DBUS_ITERATION_DO_WRITING;
1209
1210 if (_dbus_connection_acquire_io_path (connection,
1211 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
1212 {
1213 HAVE_LOCK_CHECK (connection);
1214
1215 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
1216 {
1217 _dbus_verbose ("pending call completed while acquiring I/O path");
1218 }
1219 else if ( (pending != NULL) &&
1220 _dbus_connection_peek_for_reply_unlocked (connection,
1222 {
1223 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
1224 }
1225 else
1226 {
1228 flags, timeout_milliseconds);
1229 }
1230
1231 _dbus_connection_release_io_path (connection);
1232 }
1233
1234 HAVE_LOCK_CHECK (connection);
1235
1236 _dbus_verbose ("end\n");
1237}
1238
1250{
1251 DBusConnection *connection;
1252 DBusWatchList *watch_list;
1253 DBusTimeoutList *timeout_list;
1254 DBusHashTable *pending_replies;
1255 DBusList *disconnect_link;
1256 DBusMessage *disconnect_message;
1257 DBusCounter *outgoing_counter;
1258 DBusObjectTree *objects;
1259
1260 watch_list = NULL;
1261 connection = NULL;
1262 pending_replies = NULL;
1263 timeout_list = NULL;
1264 disconnect_link = NULL;
1265 disconnect_message = NULL;
1266 outgoing_counter = NULL;
1267 objects = NULL;
1268
1269 watch_list = _dbus_watch_list_new ();
1270 if (watch_list == NULL)
1271 goto error;
1272
1273 timeout_list = _dbus_timeout_list_new ();
1274 if (timeout_list == NULL)
1275 goto error;
1276
1277 pending_replies =
1279 NULL,
1280 (DBusFreeFunction)free_pending_call_on_hash_removal);
1281 if (pending_replies == NULL)
1282 goto error;
1283
1284 connection = dbus_new0 (DBusConnection, 1);
1285 if (connection == NULL)
1286 goto error;
1287
1288 _dbus_rmutex_new_at_location (&connection->mutex);
1289 if (connection->mutex == NULL)
1290 goto error;
1291
1293 if (connection->io_path_mutex == NULL)
1294 goto error;
1295
1297 if (connection->dispatch_mutex == NULL)
1298 goto error;
1299
1301 if (connection->dispatch_cond == NULL)
1302 goto error;
1303
1305 if (connection->io_path_cond == NULL)
1306 goto error;
1307
1309 if (connection->slot_mutex == NULL)
1310 goto error;
1311
1312 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
1314 "Disconnected");
1315
1316 if (disconnect_message == NULL)
1317 goto error;
1318
1319 disconnect_link = _dbus_list_alloc_link (disconnect_message);
1320 if (disconnect_link == NULL)
1321 goto error;
1322
1323 outgoing_counter = _dbus_counter_new ();
1324 if (outgoing_counter == NULL)
1325 goto error;
1326
1327 objects = _dbus_object_tree_new (connection);
1328 if (objects == NULL)
1329 goto error;
1330
1331 if (_dbus_modify_sigpipe)
1333
1334 /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
1335 _dbus_atomic_inc (&connection->refcount);
1336 connection->transport = transport;
1337 connection->watches = watch_list;
1338 connection->timeouts = timeout_list;
1339 connection->pending_replies = pending_replies;
1340 connection->outgoing_counter = outgoing_counter;
1341 connection->filter_list = NULL;
1342 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
1343 connection->objects = objects;
1344 connection->exit_on_disconnect = FALSE;
1345 connection->shareable = FALSE;
1346 connection->route_peer_messages = FALSE;
1347 connection->disconnected_message_arrived = FALSE;
1349
1350#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
1351 connection->generation = _dbus_current_generation;
1352#endif
1353
1354 _dbus_data_slot_list_init (&connection->slot_list);
1355
1356 connection->client_serial = 1;
1357
1358 connection->disconnect_message_link = disconnect_link;
1359
1360 CONNECTION_LOCK (connection);
1361
1362 if (!_dbus_transport_set_connection (transport, connection))
1363 {
1364 CONNECTION_UNLOCK (connection);
1365
1366 goto error;
1367 }
1368
1369 _dbus_transport_ref (transport);
1370
1371 CONNECTION_UNLOCK (connection);
1372
1373 _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
1374 return connection;
1375
1376 error:
1377 if (disconnect_message != NULL)
1378 dbus_message_unref (disconnect_message);
1379
1380 if (disconnect_link != NULL)
1381 _dbus_list_free_link (disconnect_link);
1382
1383 if (connection != NULL)
1384 {
1387 _dbus_rmutex_free_at_location (&connection->mutex);
1391 dbus_free (connection);
1392 }
1393 if (pending_replies)
1394 _dbus_hash_table_unref (pending_replies);
1395
1396 if (watch_list)
1397 _dbus_watch_list_free (watch_list);
1398
1399 if (timeout_list)
1400 _dbus_timeout_list_free (timeout_list);
1401
1402 if (outgoing_counter)
1403 _dbus_counter_unref (outgoing_counter);
1404
1405 if (objects)
1406 _dbus_object_tree_unref (objects);
1407
1408 return NULL;
1409}
1410
1420{
1421 dbus_int32_t old_refcount;
1422
1423 _dbus_assert (connection != NULL);
1424 _dbus_assert (connection->generation == _dbus_current_generation);
1425
1426 HAVE_LOCK_CHECK (connection);
1427
1428 old_refcount = _dbus_atomic_inc (&connection->refcount);
1429 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
1430 "ref_unlocked");
1431
1432 return connection;
1433}
1434
1441void
1443{
1444 dbus_int32_t old_refcount;
1445
1446 HAVE_LOCK_CHECK (connection);
1447
1448 _dbus_assert (connection != NULL);
1449
1450 old_refcount = _dbus_atomic_dec (&connection->refcount);
1451
1452 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
1453 "unref_unlocked");
1454
1455 if (old_refcount == 1)
1456 _dbus_connection_last_unref (connection);
1457}
1458
1470{
1471 dbus_uint32_t serial;
1472
1473 serial = connection->client_serial++;
1474
1475 if (connection->client_serial == 0)
1476 connection->client_serial = 1;
1477
1478 return serial;
1479}
1480
1496 unsigned int condition,
1497 void *data)
1498{
1499 DBusConnection *connection;
1500 dbus_bool_t retval;
1501 DBusDispatchStatus status;
1502
1503 connection = data;
1504
1505 _dbus_verbose ("start\n");
1506
1507 CONNECTION_LOCK (connection);
1508
1509 if (!_dbus_connection_acquire_io_path (connection, 1))
1510 {
1511 /* another thread is handling the message */
1512 CONNECTION_UNLOCK (connection);
1513 return TRUE;
1514 }
1515
1516 HAVE_LOCK_CHECK (connection);
1517 retval = _dbus_transport_handle_watch (connection->transport,
1518 watch, condition);
1519
1520 _dbus_connection_release_io_path (connection);
1521
1522 HAVE_LOCK_CHECK (connection);
1523
1524 _dbus_verbose ("middle\n");
1525
1526 status = _dbus_connection_get_dispatch_status_unlocked (connection);
1527
1528 /* this calls out to user code */
1529 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
1530
1531 _dbus_verbose ("end\n");
1532
1533 return retval;
1534}
1535
1536/* Protected by _DBUS_LOCK (shared_connections) */
1537static DBusHashTable *shared_connections = NULL;
1538static DBusList *shared_connections_no_guid = NULL;
1539
1540static void
1541close_connection_on_shutdown (DBusConnection *connection)
1542{
1543 DBusMessage *message;
1544
1545 dbus_connection_ref (connection);
1547
1548 /* Churn through to the Disconnected message */
1549 while ((message = dbus_connection_pop_message (connection)))
1550 {
1551 dbus_message_unref (message);
1552 }
1553 dbus_connection_unref (connection);
1554}
1555
1556static void
1557shared_connections_shutdown (void *data)
1558{
1559 int n_entries;
1560
1561 if (!_DBUS_LOCK (shared_connections))
1562 {
1563 /* We'd have initialized locks before adding anything, so there
1564 * can't be anything there. */
1565 return;
1566 }
1567
1568 /* This is a little bit unpleasant... better ideas? */
1569 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
1570 {
1571 DBusConnection *connection;
1572 DBusHashIter iter;
1573
1574 _dbus_hash_iter_init (shared_connections, &iter);
1575 _dbus_hash_iter_next (&iter);
1576
1577 connection = _dbus_hash_iter_get_value (&iter);
1578
1579 _DBUS_UNLOCK (shared_connections);
1580 close_connection_on_shutdown (connection);
1581 if (!_DBUS_LOCK (shared_connections))
1582 _dbus_assert_not_reached ("global locks were already initialized");
1583
1584 /* The connection should now be dead and not in our hash ... */
1585 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
1586 }
1587
1588 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
1589
1590 _dbus_hash_table_unref (shared_connections);
1591 shared_connections = NULL;
1592
1593 if (shared_connections_no_guid != NULL)
1594 {
1595 DBusConnection *connection;
1596 connection = _dbus_list_pop_first (&shared_connections_no_guid);
1597 while (connection != NULL)
1598 {
1599 _DBUS_UNLOCK (shared_connections);
1600 close_connection_on_shutdown (connection);
1601 if (!_DBUS_LOCK (shared_connections))
1602 _dbus_assert_not_reached ("global locks were already initialized");
1603 connection = _dbus_list_pop_first (&shared_connections_no_guid);
1604 }
1605 }
1606
1607 shared_connections_no_guid = NULL;
1608
1609 _DBUS_UNLOCK (shared_connections);
1610}
1611
1612static dbus_bool_t
1613connection_lookup_shared (DBusAddressEntry *entry,
1614 DBusConnection **result)
1615{
1616 _dbus_verbose ("checking for existing connection\n");
1617
1618 *result = NULL;
1619
1620 if (!_DBUS_LOCK (shared_connections))
1621 {
1622 /* If it was shared, we'd have initialized global locks when we put
1623 * it in shared_connections. */
1624 return FALSE;
1625 }
1626
1627 if (shared_connections == NULL)
1628 {
1629 _dbus_verbose ("creating shared_connections hash table\n");
1630
1631 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
1632 dbus_free,
1633 NULL);
1634 if (shared_connections == NULL)
1635 {
1636 _DBUS_UNLOCK (shared_connections);
1637 return FALSE;
1638 }
1639
1640 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
1641 {
1642 _dbus_hash_table_unref (shared_connections);
1643 shared_connections = NULL;
1644 _DBUS_UNLOCK (shared_connections);
1645 return FALSE;
1646 }
1647
1648 _dbus_verbose (" successfully created shared_connections\n");
1649
1650 _DBUS_UNLOCK (shared_connections);
1651 return TRUE; /* no point looking up in the hash we just made */
1652 }
1653 else
1654 {
1655 const char *guid;
1656
1657 guid = dbus_address_entry_get_value (entry, "guid");
1658
1659 if (guid != NULL)
1660 {
1661 DBusConnection *connection;
1662
1663 connection = _dbus_hash_table_lookup_string (shared_connections,
1664 guid);
1665
1666 if (connection)
1667 {
1668 /* The DBusConnection can't be finalized without taking
1669 * the shared_connections lock to remove it from the
1670 * hash. So it's safe to ref the connection here.
1671 * However, it may be disconnected if the Disconnected
1672 * message hasn't been processed yet, in which case we
1673 * want to pretend it isn't in the hash and avoid
1674 * returning it.
1675 *
1676 * The idea is to avoid ever returning a disconnected connection
1677 * from dbus_connection_open(). We could just synchronously
1678 * drop our shared ref to the connection on connection disconnect,
1679 * and then assert here that the connection is connected, but
1680 * that causes reentrancy headaches.
1681 */
1682 CONNECTION_LOCK (connection);
1683 if (_dbus_connection_get_is_connected_unlocked (connection))
1684 {
1685 _dbus_connection_ref_unlocked (connection);
1686 *result = connection;
1687 _dbus_verbose ("looked up existing connection to server guid %s\n",
1688 guid);
1689 }
1690 else
1691 {
1692 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
1693 guid);
1694 }
1695 CONNECTION_UNLOCK (connection);
1696 }
1697 }
1698
1699 _DBUS_UNLOCK (shared_connections);
1700 return TRUE;
1701 }
1702}
1703
1704static dbus_bool_t
1705connection_record_shared_unlocked (DBusConnection *connection,
1706 const char *guid)
1707{
1708 char *guid_key;
1709 char *guid_in_connection;
1710
1711 HAVE_LOCK_CHECK (connection);
1712 _dbus_assert (connection->server_guid == NULL);
1713 _dbus_assert (connection->shareable);
1714
1715 /* get a hard ref on this connection, even if
1716 * we won't in fact store it in the hash, we still
1717 * need to hold a ref on it until it's disconnected.
1718 */
1719 _dbus_connection_ref_unlocked (connection);
1720
1721 if (guid == NULL)
1722 {
1723 if (!_DBUS_LOCK (shared_connections))
1724 return FALSE;
1725
1726 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
1727 {
1728 _DBUS_UNLOCK (shared_connections);
1729 return FALSE;
1730 }
1731
1732 _DBUS_UNLOCK (shared_connections);
1733 return TRUE; /* don't store in the hash */
1734 }
1735
1736 /* A separate copy of the key is required in the hash table, because
1737 * we don't have a lock on the connection when we are doing a hash
1738 * lookup.
1739 */
1740
1741 guid_key = _dbus_strdup (guid);
1742 if (guid_key == NULL)
1743 return FALSE;
1744
1745 guid_in_connection = _dbus_strdup (guid);
1746 if (guid_in_connection == NULL)
1747 {
1748 dbus_free (guid_key);
1749 return FALSE;
1750 }
1751
1752 if (!_DBUS_LOCK (shared_connections))
1753 {
1754 dbus_free (guid_in_connection);
1755 dbus_free (guid_key);
1756 return FALSE;
1757 }
1758
1759 _dbus_assert (shared_connections != NULL);
1760
1761 if (!_dbus_hash_table_insert_string (shared_connections,
1762 guid_key, connection))
1763 {
1764 dbus_free (guid_key);
1765 dbus_free (guid_in_connection);
1766 _DBUS_UNLOCK (shared_connections);
1767 return FALSE;
1768 }
1769
1770 connection->server_guid = guid_in_connection;
1771
1772 _dbus_verbose ("stored connection to %s to be shared\n",
1773 connection->server_guid);
1774
1775 _DBUS_UNLOCK (shared_connections);
1776
1777 _dbus_assert (connection->server_guid != NULL);
1778
1779 return TRUE;
1780}
1781
1782static void
1783connection_forget_shared_unlocked (DBusConnection *connection)
1784{
1785 HAVE_LOCK_CHECK (connection);
1786
1787 if (!connection->shareable)
1788 return;
1789
1790 if (!_DBUS_LOCK (shared_connections))
1791 {
1792 /* If it was shared, we'd have initialized global locks when we put
1793 * it in the table; so it can't be there. */
1794 return;
1795 }
1796
1797 if (connection->server_guid != NULL)
1798 {
1799 _dbus_verbose ("dropping connection to %s out of the shared table\n",
1800 connection->server_guid);
1801
1802 if (!_dbus_hash_table_remove_string (shared_connections,
1803 connection->server_guid))
1804 _dbus_assert_not_reached ("connection was not in the shared table");
1805
1806 dbus_free (connection->server_guid);
1807 connection->server_guid = NULL;
1808 }
1809 else
1810 {
1811 _dbus_list_remove (&shared_connections_no_guid, connection);
1812 }
1813
1814 _DBUS_UNLOCK (shared_connections);
1815
1816 /* remove our reference held on all shareable connections */
1818}
1819
1820static DBusConnection*
1821connection_try_from_address_entry (DBusAddressEntry *entry,
1822 DBusError *error)
1823{
1824 DBusTransport *transport;
1825 DBusConnection *connection;
1826
1827 transport = _dbus_transport_open (entry, error);
1828
1829 if (transport == NULL)
1830 {
1831 _DBUS_ASSERT_ERROR_IS_SET (error);
1832 return NULL;
1833 }
1834
1835 connection = _dbus_connection_new_for_transport (transport);
1836
1837 _dbus_transport_unref (transport);
1838
1839 if (connection == NULL)
1840 {
1841 _DBUS_SET_OOM (error);
1842 return NULL;
1843 }
1844
1845#ifndef DBUS_DISABLE_CHECKS
1846 _dbus_assert (!connection->have_connection_lock);
1847#endif
1848 return connection;
1849}
1850
1851/*
1852 * If the shared parameter is true, then any existing connection will
1853 * be used (and if a new connection is created, it will be available
1854 * for use by others). If the shared parameter is false, a new
1855 * connection will always be created, and the new connection will
1856 * never be returned to other callers.
1857 *
1858 * @param address the address
1859 * @param shared whether the connection is shared or private
1860 * @param error error return
1861 * @returns the connection or #NULL on error
1862 */
1863static DBusConnection*
1864_dbus_connection_open_internal (const char *address,
1865 dbus_bool_t shared,
1866 DBusError *error)
1867{
1868 DBusConnection *connection;
1869 DBusAddressEntry **entries;
1870 DBusError tmp_error = DBUS_ERROR_INIT;
1871 DBusError first_error = DBUS_ERROR_INIT;
1872 int len, i;
1873
1874 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1875
1876 _dbus_verbose ("opening %s connection to: %s\n",
1877 shared ? "shared" : "private", address);
1878
1879 if (!dbus_parse_address (address, &entries, &len, error))
1880 return NULL;
1881
1882 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1883
1884 connection = NULL;
1885
1886 for (i = 0; i < len; i++)
1887 {
1888 if (shared)
1889 {
1890 if (!connection_lookup_shared (entries[i], &connection))
1891 _DBUS_SET_OOM (&tmp_error);
1892 }
1893
1894 if (connection == NULL)
1895 {
1896 connection = connection_try_from_address_entry (entries[i],
1897 &tmp_error);
1898
1899 if (connection != NULL && shared)
1900 {
1901 const char *guid;
1902
1903 connection->shareable = TRUE;
1904
1905 /* guid may be NULL */
1906 guid = dbus_address_entry_get_value (entries[i], "guid");
1907
1908 CONNECTION_LOCK (connection);
1909
1910 if (!connection_record_shared_unlocked (connection, guid))
1911 {
1912 _DBUS_SET_OOM (&tmp_error);
1913 _dbus_connection_close_possibly_shared_and_unlock (connection);
1914 dbus_connection_unref (connection);
1915 connection = NULL;
1916 }
1917 else
1918 CONNECTION_UNLOCK (connection);
1919 }
1920 }
1921
1922 if (connection)
1923 break;
1924
1925 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1926
1927 if (i == 0)
1928 dbus_move_error (&tmp_error, &first_error);
1929 else
1930 dbus_error_free (&tmp_error);
1931 }
1932
1933 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1934 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1935
1936 if (connection == NULL)
1937 {
1938 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
1939 dbus_move_error (&first_error, error);
1940 }
1941 else
1942 dbus_error_free (&first_error);
1943
1944 dbus_address_entries_free (entries);
1945 return connection;
1946}
1947
1956void
1958{
1959 _dbus_assert (connection != NULL);
1960 _dbus_assert (connection->generation == _dbus_current_generation);
1961
1962 CONNECTION_LOCK (connection);
1963 _dbus_connection_close_possibly_shared_and_unlock (connection);
1964}
1965
1967_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
1968{
1969 DBusPreallocatedSend *preallocated;
1970
1971 HAVE_LOCK_CHECK (connection);
1972
1973 _dbus_assert (connection != NULL);
1974
1975 preallocated = dbus_new (DBusPreallocatedSend, 1);
1976 if (preallocated == NULL)
1977 return NULL;
1978
1979 preallocated->queue_link = _dbus_list_alloc_link (NULL);
1980 if (preallocated->queue_link == NULL)
1981 goto failed_0;
1982
1983 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
1984 if (preallocated->counter_link == NULL)
1985 goto failed_1;
1986
1987 _dbus_counter_ref (preallocated->counter_link->data);
1988
1989 preallocated->connection = connection;
1990
1991 return preallocated;
1992
1993 failed_1:
1994 _dbus_list_free_link (preallocated->queue_link);
1995 failed_0:
1996 dbus_free (preallocated);
1997
1998 return NULL;
1999}
2000
2001/* Called with lock held, does not update dispatch status */
2002static void
2003_dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
2004 DBusPreallocatedSend *preallocated,
2005 DBusMessage *message,
2006 dbus_uint32_t *client_serial)
2007{
2008 dbus_uint32_t serial;
2009
2010 preallocated->queue_link->data = message;
2012 preallocated->queue_link);
2013
2014 /* It's OK that we'll never call the notify function, because for the
2015 * outgoing limit, there isn't one */
2017 preallocated->counter_link);
2018
2019 dbus_free (preallocated);
2020 preallocated = NULL;
2021
2022 dbus_message_ref (message);
2023
2024 connection->n_outgoing += 1;
2025
2026 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
2027 message,
2029 dbus_message_get_path (message) ?
2030 dbus_message_get_path (message) :
2031 "no path",
2032 dbus_message_get_interface (message) ?
2033 dbus_message_get_interface (message) :
2034 "no interface",
2035 dbus_message_get_member (message) ?
2036 dbus_message_get_member (message) :
2037 "no member",
2041 "null",
2042 connection,
2043 connection->n_outgoing);
2044
2045 if (dbus_message_get_serial (message) == 0)
2046 {
2047 serial = _dbus_connection_get_next_client_serial (connection);
2048 dbus_message_set_serial (message, serial);
2049 if (client_serial)
2050 *client_serial = serial;
2051 }
2052 else
2053 {
2054 if (client_serial)
2055 *client_serial = dbus_message_get_serial (message);
2056 }
2057
2058 _dbus_verbose ("Message %p serial is %u\n",
2059 message, dbus_message_get_serial (message));
2060
2061 dbus_message_lock (message);
2062
2063 /* Now we need to run an iteration to hopefully just write the messages
2064 * out immediately, and otherwise get them queued up
2065 */
2067 NULL,
2068 DBUS_ITERATION_DO_WRITING,
2069 -1);
2070
2071 /* If stuff is still queued up, be sure we wake up the main loop */
2072 if (connection->n_outgoing > 0)
2073 _dbus_connection_wakeup_mainloop (connection);
2074}
2075
2076static void
2077_dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
2078 DBusPreallocatedSend *preallocated,
2079 DBusMessage *message,
2080 dbus_uint32_t *client_serial)
2081{
2082 DBusDispatchStatus status;
2083
2084 HAVE_LOCK_CHECK (connection);
2085
2086 _dbus_connection_send_preallocated_unlocked_no_update (connection,
2087 preallocated,
2088 message, client_serial);
2089
2090 _dbus_verbose ("middle\n");
2091 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2092
2093 /* this calls out to user code */
2094 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2095}
2096
2108 DBusMessage *message,
2109 dbus_uint32_t *client_serial)
2110{
2111 DBusPreallocatedSend *preallocated;
2112
2113 _dbus_assert (connection != NULL);
2114 _dbus_assert (message != NULL);
2115
2116 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
2117 if (preallocated == NULL)
2118 {
2119 CONNECTION_UNLOCK (connection);
2120 return FALSE;
2121 }
2122
2123 _dbus_connection_send_preallocated_and_unlock (connection,
2124 preallocated,
2125 message,
2126 client_serial);
2127 return TRUE;
2128}
2129
2154void
2156{
2157 dbus_int32_t refcount;
2158
2159 CONNECTION_LOCK (connection);
2160
2161 refcount = _dbus_atomic_get (&connection->refcount);
2162 /* The caller should have at least one ref */
2163 _dbus_assert (refcount >= 1);
2164
2165 if (refcount == 1)
2166 _dbus_connection_close_possibly_shared_and_unlock (connection);
2167 else
2168 CONNECTION_UNLOCK (connection);
2169}
2170
2171
2181static void
2182_dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
2183{
2184 if (timeout_milliseconds == -1)
2186 else if (timeout_milliseconds < 100)
2187 ; /* just busy loop */
2188 else if (timeout_milliseconds <= 1000)
2189 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
2190 else
2192}
2193
2194static DBusMessage *
2195generate_local_error_message (dbus_uint32_t serial,
2196 const char *error_name,
2197 const char *error_msg)
2198{
2199 DBusMessage *message;
2201 if (!message)
2202 goto out;
2203
2204 if (!dbus_message_set_error_name (message, error_name))
2205 {
2206 dbus_message_unref (message);
2207 message = NULL;
2208 goto out;
2209 }
2210
2211 dbus_message_set_no_reply (message, TRUE);
2212
2213 if (!dbus_message_set_reply_serial (message,
2214 serial))
2215 {
2216 dbus_message_unref (message);
2217 message = NULL;
2218 goto out;
2219 }
2220
2221 if (error_msg != NULL)
2222 {
2223 DBusMessageIter iter;
2224
2225 dbus_message_iter_init_append (message, &iter);
2228 &error_msg))
2229 {
2230 dbus_message_unref (message);
2231 message = NULL;
2232 goto out;
2233 }
2234 }
2235
2236 out:
2237 return message;
2238}
2239
2240/*
2241 * Peek the incoming queue to see if we got reply for a specific serial
2242 */
2243static dbus_bool_t
2244_dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
2245 dbus_uint32_t client_serial)
2246{
2247 DBusList *link;
2248 HAVE_LOCK_CHECK (connection);
2249
2250 link = _dbus_list_get_first_link (&connection->incoming_messages);
2251
2252 while (link != NULL)
2253 {
2254 DBusMessage *reply = link->data;
2255
2256 if (dbus_message_get_reply_serial (reply) == client_serial)
2257 {
2258 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
2259 return TRUE;
2260 }
2261 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2262 }
2263
2264 return FALSE;
2265}
2266
2267/* This is slightly strange since we can pop a message here without
2268 * the dispatch lock.
2269 */
2270static DBusMessage*
2271check_for_reply_unlocked (DBusConnection *connection,
2272 dbus_uint32_t client_serial)
2273{
2274 DBusList *link;
2275
2276 HAVE_LOCK_CHECK (connection);
2277
2278 link = _dbus_list_get_first_link (&connection->incoming_messages);
2279
2280 while (link != NULL)
2281 {
2282 DBusMessage *reply = link->data;
2283
2284 if (dbus_message_get_reply_serial (reply) == client_serial)
2285 {
2286 _dbus_list_remove_link (&connection->incoming_messages, link);
2287 connection->n_incoming -= 1;
2288 return reply;
2289 }
2290 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2291 }
2292
2293 return NULL;
2294}
2295
2296static void
2297connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
2298{
2299 /* We can't iterate over the hash in the normal way since we'll be
2300 * dropping the lock for each item. So we restart the
2301 * iter each time as we drain the hash table.
2302 */
2303
2304 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
2305 {
2306 DBusPendingCall *pending;
2307 DBusHashIter iter;
2308
2309 _dbus_hash_iter_init (connection->pending_replies, &iter);
2310 _dbus_hash_iter_next (&iter);
2311
2312 pending = _dbus_hash_iter_get_value (&iter);
2314
2316 connection);
2317
2323
2325 CONNECTION_LOCK (connection);
2326 }
2327 HAVE_LOCK_CHECK (connection);
2328}
2329
2330static void
2331complete_pending_call_and_unlock (DBusConnection *connection,
2332 DBusPendingCall *pending,
2333 DBusMessage *message)
2334{
2335 _dbus_pending_call_set_reply_unlocked (pending, message);
2336 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
2338 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
2339
2340 /* Must be called unlocked since it invokes app callback */
2342 dbus_pending_call_unref (pending);
2343}
2344
2345static dbus_bool_t
2346check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
2347 DBusPendingCall *pending)
2348{
2349 DBusMessage *reply;
2350 DBusDispatchStatus status;
2351
2352 reply = check_for_reply_unlocked (connection,
2354 if (reply != NULL)
2355 {
2356 _dbus_verbose ("checked for reply\n");
2357
2358 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
2359
2360 complete_pending_call_and_unlock (connection, pending, reply);
2361 dbus_message_unref (reply);
2362
2363 CONNECTION_LOCK (connection);
2364 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2365 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2366 dbus_pending_call_unref (pending);
2367
2368 return TRUE;
2369 }
2370
2371 return FALSE;
2372}
2373
2388void
2390{
2391 long start_tv_sec, start_tv_usec;
2392 long tv_sec, tv_usec;
2393 DBusDispatchStatus status;
2394 DBusConnection *connection;
2395 dbus_uint32_t client_serial;
2396 DBusTimeout *timeout;
2397 int timeout_milliseconds, elapsed_milliseconds;
2398
2399 _dbus_assert (pending != NULL);
2400
2401 if (dbus_pending_call_get_completed (pending))
2402 return;
2403
2404 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
2405
2406 connection = _dbus_pending_call_get_connection_and_lock (pending);
2407
2408 /* Flush message queue - note, can affect dispatch status */
2409 _dbus_connection_flush_unlocked (connection);
2410
2411 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
2412
2413 /* note that timeout_milliseconds is limited to a smallish value
2414 * in _dbus_pending_call_new() so overflows aren't possible
2415 * below
2416 */
2417 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
2418 _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
2419 if (timeout)
2420 {
2421 timeout_milliseconds = dbus_timeout_get_interval (timeout);
2422
2423 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
2424 timeout_milliseconds,
2425 client_serial,
2426 start_tv_sec, start_tv_usec);
2427 }
2428 else
2429 {
2430 timeout_milliseconds = -1;
2431
2432 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
2433 }
2434
2435 /* check to see if we already got the data off the socket */
2436 /* from another blocked pending call */
2437 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2438 return;
2439
2440 /* Now we wait... */
2441 /* always block at least once as we know we don't have the reply yet */
2443 pending,
2444 DBUS_ITERATION_DO_READING |
2445 DBUS_ITERATION_BLOCK,
2446 timeout_milliseconds);
2447
2448 recheck_status:
2449
2450 _dbus_verbose ("top of recheck\n");
2451
2452 HAVE_LOCK_CHECK (connection);
2453
2454 /* queue messages and get status */
2455
2456 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2457
2458 /* the get_completed() is in case a dispatch() while we were blocking
2459 * got the reply instead of us.
2460 */
2462 {
2463 _dbus_verbose ("Pending call completed by dispatch\n");
2464 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2465 dbus_pending_call_unref (pending);
2466 return;
2467 }
2468
2469 if (status == DBUS_DISPATCH_DATA_REMAINS)
2470 {
2471 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2472 return;
2473 }
2474
2475 _dbus_get_monotonic_time (&tv_sec, &tv_usec);
2476 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
2477 (tv_usec - start_tv_usec) / 1000;
2478
2479 if (!_dbus_connection_get_is_connected_unlocked (connection))
2480 {
2481 DBusMessage *error_msg;
2482
2483 error_msg = generate_local_error_message (client_serial,
2485 "Connection was disconnected before a reply was received");
2486
2487 /* on OOM error_msg is set to NULL */
2488 complete_pending_call_and_unlock (connection, pending, error_msg);
2489 if (error_msg != NULL)
2490 dbus_message_unref (error_msg);
2491 dbus_pending_call_unref (pending);
2492 return;
2493 }
2494 else if (connection->disconnect_message_link == NULL)
2495 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
2496 else if (timeout == NULL)
2497 {
2498 if (status == DBUS_DISPATCH_NEED_MEMORY)
2499 {
2500 /* Try sleeping a bit, as we aren't sure we need to block for reading,
2501 * we may already have a reply in the buffer and just can't process
2502 * it.
2503 */
2504 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2505
2506 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2507 }
2508 else
2509 {
2510 /* block again, we don't have the reply buffered yet. */
2512 pending,
2513 DBUS_ITERATION_DO_READING |
2514 DBUS_ITERATION_BLOCK,
2515 timeout_milliseconds - elapsed_milliseconds);
2516 }
2517
2518 goto recheck_status;
2519 }
2520 else if (tv_sec < start_tv_sec)
2521 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
2522 else if (elapsed_milliseconds < timeout_milliseconds)
2523 {
2524 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
2525
2526 if (status == DBUS_DISPATCH_NEED_MEMORY)
2527 {
2528 /* Try sleeping a bit, as we aren't sure we need to block for reading,
2529 * we may already have a reply in the buffer and just can't process
2530 * it.
2531 */
2532 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2533
2534 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2535 }
2536 else
2537 {
2538 /* block again, we don't have the reply buffered yet. */
2540 pending,
2541 DBUS_ITERATION_DO_READING |
2542 DBUS_ITERATION_BLOCK,
2543 timeout_milliseconds - elapsed_milliseconds);
2544 }
2545
2546 goto recheck_status;
2547 }
2548
2549 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
2550 elapsed_milliseconds);
2551
2553
2554 /* unlock and call user code */
2555 complete_pending_call_and_unlock (connection, pending, NULL);
2556
2557 /* update user code on dispatch status */
2558 CONNECTION_LOCK (connection);
2559 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2560 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2561 dbus_pending_call_unref (pending);
2562}
2563
2569int
2571{
2573}
2574
2582void
2584 DBusPendingFdsChangeFunction callback,
2585 void *data)
2586{
2588 callback, data);
2589}
2590
2628dbus_connection_open (const char *address,
2629 DBusError *error)
2630{
2631 DBusConnection *connection;
2632
2633 _dbus_return_val_if_fail (address != NULL, NULL);
2634 _dbus_return_val_if_error_is_set (error, NULL);
2635
2636 connection = _dbus_connection_open_internal (address,
2637 TRUE,
2638 error);
2639
2640 return connection;
2641}
2642
2671dbus_connection_open_private (const char *address,
2672 DBusError *error)
2673{
2674 DBusConnection *connection;
2675
2676 _dbus_return_val_if_fail (address != NULL, NULL);
2677 _dbus_return_val_if_error_is_set (error, NULL);
2678
2679 connection = _dbus_connection_open_internal (address,
2680 FALSE,
2681 error);
2682
2683 return connection;
2684}
2685
2694{
2695 dbus_int32_t old_refcount;
2696
2697 _dbus_return_val_if_fail (connection != NULL, NULL);
2698 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
2699 old_refcount = _dbus_atomic_inc (&connection->refcount);
2700 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
2701 "ref");
2702
2703 return connection;
2704}
2705
2706static void
2707free_outgoing_message (void *element,
2708 void *data)
2709{
2710 DBusMessage *message = element;
2711 DBusConnection *connection = data;
2712
2713 _dbus_message_remove_counter (message, connection->outgoing_counter);
2714 dbus_message_unref (message);
2715}
2716
2717/* This is run without the mutex held, but after the last reference
2718 * to the connection has been dropped we should have no thread-related
2719 * problems
2720 */
2721static void
2722_dbus_connection_last_unref (DBusConnection *connection)
2723{
2724 DBusList *link;
2725
2726 _dbus_verbose ("Finalizing connection %p\n", connection);
2727
2728 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
2729
2730 /* You have to disconnect the connection before unref:ing it. Otherwise
2731 * you won't get the disconnected message.
2732 */
2734 _dbus_assert (connection->server_guid == NULL);
2735
2736 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
2738
2743
2744 _dbus_watch_list_free (connection->watches);
2745 connection->watches = NULL;
2746
2747 _dbus_timeout_list_free (connection->timeouts);
2748 connection->timeouts = NULL;
2749
2750 _dbus_data_slot_list_free (&connection->slot_list);
2751
2752 link = _dbus_list_get_first_link (&connection->filter_list);
2753 while (link != NULL)
2754 {
2755 DBusMessageFilter *filter = link->data;
2756 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
2757
2758 filter->function = NULL;
2759 _dbus_message_filter_unref (filter); /* calls app callback */
2760 link->data = NULL;
2761
2762 link = next;
2763 }
2764 _dbus_list_clear (&connection->filter_list);
2765
2766 /* ---- Done with stuff that invokes application callbacks */
2767
2768 _dbus_object_tree_unref (connection->objects);
2769
2771 connection->pending_replies = NULL;
2772
2774 free_outgoing_message,
2775 connection);
2776 _dbus_list_clear (&connection->outgoing_messages);
2777
2780 NULL);
2781 _dbus_list_clear (&connection->incoming_messages);
2782
2784
2785 _dbus_transport_unref (connection->transport);
2786
2787 if (connection->disconnect_message_link)
2788 {
2789 DBusMessage *message = connection->disconnect_message_link->data;
2790 dbus_message_unref (message);
2792 }
2793
2796
2799
2801
2802 _dbus_rmutex_free_at_location (&connection->mutex);
2803
2804 dbus_free (connection);
2805}
2806
2826void
2828{
2829 dbus_int32_t old_refcount;
2830
2831 _dbus_return_if_fail (connection != NULL);
2832 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2833
2834 old_refcount = _dbus_atomic_dec (&connection->refcount);
2835
2836 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
2837 "unref");
2838
2839 if (old_refcount == 1)
2840 {
2841#ifndef DBUS_DISABLE_CHECKS
2843 {
2844 _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",
2845 connection->shareable ?
2846 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
2847 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
2848 return;
2849 }
2850#endif
2851 _dbus_connection_last_unref (connection);
2852 }
2853}
2854
2855/*
2856 * Note that the transport can disconnect itself (other end drops us)
2857 * and in that case this function never runs. So this function must
2858 * not do anything more than disconnect the transport and update the
2859 * dispatch status.
2860 *
2861 * If the transport self-disconnects, then we assume someone will
2862 * dispatch the connection to cause the dispatch status update.
2863 */
2864static void
2865_dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
2866{
2867 DBusDispatchStatus status;
2868
2869 HAVE_LOCK_CHECK (connection);
2870
2871 _dbus_verbose ("Disconnecting %p\n", connection);
2872
2873 /* We need to ref because update_dispatch_status_and_unlock will unref
2874 * the connection if it was shared and libdbus was the only remaining
2875 * refcount holder.
2876 */
2877 _dbus_connection_ref_unlocked (connection);
2878
2880
2881 /* This has the side effect of queuing the disconnect message link
2882 * (unless we don't have enough memory, possibly, so don't assert it).
2883 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
2884 * should never again return the newly-disconnected connection.
2885 *
2886 * However, we only unref the shared connection and exit_on_disconnect when
2887 * the disconnect message reaches the head of the message queue,
2888 * NOT when it's first queued.
2889 */
2890 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2891
2892 /* This calls out to user code */
2893 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2894
2895 /* Could also call out to user code */
2896 dbus_connection_unref (connection);
2897}
2898
2941void
2943{
2944 _dbus_return_if_fail (connection != NULL);
2945 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2946
2947 CONNECTION_LOCK (connection);
2948
2949#ifndef DBUS_DISABLE_CHECKS
2950 if (connection->shareable)
2951 {
2952 CONNECTION_UNLOCK (connection);
2953
2954 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
2955 return;
2956 }
2957#endif
2958
2959 _dbus_connection_close_possibly_shared_and_unlock (connection);
2960}
2961
2962static dbus_bool_t
2963_dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
2964{
2965 HAVE_LOCK_CHECK (connection);
2966 return _dbus_transport_get_is_connected (connection->transport);
2967}
2968
2984{
2985 dbus_bool_t res;
2986
2987 _dbus_return_val_if_fail (connection != NULL, FALSE);
2988
2989 CONNECTION_LOCK (connection);
2990 res = _dbus_connection_get_is_connected_unlocked (connection);
2991 CONNECTION_UNLOCK (connection);
2992
2993 return res;
2994}
2995
3006{
3007 dbus_bool_t res;
3008
3009 _dbus_return_val_if_fail (connection != NULL, FALSE);
3010
3011 CONNECTION_LOCK (connection);
3013 CONNECTION_UNLOCK (connection);
3014
3015 return res;
3016}
3017
3040{
3041 dbus_bool_t res;
3042
3043 _dbus_return_val_if_fail (connection != NULL, FALSE);
3044
3045 CONNECTION_LOCK (connection);
3046 res = _dbus_transport_get_is_anonymous (connection->transport);
3047 CONNECTION_UNLOCK (connection);
3048
3049 return res;
3050}
3051
3083char*
3085{
3086 char *id;
3087
3088 _dbus_return_val_if_fail (connection != NULL, NULL);
3089
3090 CONNECTION_LOCK (connection);
3092 CONNECTION_UNLOCK (connection);
3093
3094 return id;
3095}
3096
3116 int type)
3117{
3118 _dbus_return_val_if_fail (connection != NULL, FALSE);
3119
3120 if (!dbus_type_is_valid (type))
3121 return FALSE;
3122
3123 if (type != DBUS_TYPE_UNIX_FD)
3124 return TRUE;
3125
3126#ifdef HAVE_UNIX_FD_PASSING
3127 {
3128 dbus_bool_t b;
3129
3130 CONNECTION_LOCK(connection);
3132 CONNECTION_UNLOCK(connection);
3133
3134 return b;
3135 }
3136#endif
3137
3138 return FALSE;
3139}
3140
3154void
3156 dbus_bool_t exit_on_disconnect)
3157{
3158 _dbus_return_if_fail (connection != NULL);
3159
3160 CONNECTION_LOCK (connection);
3161 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
3162 CONNECTION_UNLOCK (connection);
3163}
3164
3176{
3177 DBusPreallocatedSend *preallocated;
3178
3179 _dbus_return_val_if_fail (connection != NULL, NULL);
3180
3181 CONNECTION_LOCK (connection);
3182
3183 preallocated =
3184 _dbus_connection_preallocate_send_unlocked (connection);
3185
3186 CONNECTION_UNLOCK (connection);
3187
3188 return preallocated;
3189}
3190
3200void
3202 DBusPreallocatedSend *preallocated)
3203{
3204 _dbus_return_if_fail (connection != NULL);
3205 _dbus_return_if_fail (preallocated != NULL);
3206 _dbus_return_if_fail (connection == preallocated->connection);
3207
3208 _dbus_list_free_link (preallocated->queue_link);
3209 _dbus_counter_unref (preallocated->counter_link->data);
3210 _dbus_list_free_link (preallocated->counter_link);
3211 dbus_free (preallocated);
3212}
3213
3226void
3228 DBusPreallocatedSend *preallocated,
3229 DBusMessage *message,
3230 dbus_uint32_t *client_serial)
3231{
3232 _dbus_return_if_fail (connection != NULL);
3233 _dbus_return_if_fail (preallocated != NULL);
3234 _dbus_return_if_fail (message != NULL);
3235 _dbus_return_if_fail (preallocated->connection == connection);
3236 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
3237 dbus_message_get_member (message) != NULL);
3238 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
3239 (dbus_message_get_interface (message) != NULL &&
3240 dbus_message_get_member (message) != NULL));
3241
3242 CONNECTION_LOCK (connection);
3243
3244#ifdef HAVE_UNIX_FD_PASSING
3245
3246 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3247 message->n_unix_fds > 0)
3248 {
3249 /* Refuse to send fds on a connection that cannot handle
3250 them. Unfortunately we cannot return a proper error here, so
3251 the best we can is just return. */
3252 CONNECTION_UNLOCK (connection);
3253 return;
3254 }
3255
3256#endif
3257
3258 _dbus_connection_send_preallocated_and_unlock (connection,
3259 preallocated,
3260 message, client_serial);
3261}
3262
3263static dbus_bool_t
3264_dbus_connection_send_unlocked_no_update (DBusConnection *connection,
3265 DBusMessage *message,
3266 dbus_uint32_t *client_serial)
3267{
3268 DBusPreallocatedSend *preallocated;
3269
3270 _dbus_assert (connection != NULL);
3271 _dbus_assert (message != NULL);
3272
3273 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
3274 if (preallocated == NULL)
3275 return FALSE;
3276
3277 _dbus_connection_send_preallocated_unlocked_no_update (connection,
3278 preallocated,
3279 message,
3280 client_serial);
3281 return TRUE;
3282}
3283
3313 DBusMessage *message,
3314 dbus_uint32_t *serial)
3315{
3316 _dbus_return_val_if_fail (connection != NULL, FALSE);
3317 _dbus_return_val_if_fail (message != NULL, FALSE);
3318
3319 CONNECTION_LOCK (connection);
3320
3321#ifdef HAVE_UNIX_FD_PASSING
3322
3323 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3324 message->n_unix_fds > 0)
3325 {
3326 /* Refuse to send fds on a connection that cannot handle
3327 them. Unfortunately we cannot return a proper error here, so
3328 the best we can is just return. */
3329 CONNECTION_UNLOCK (connection);
3330 return FALSE;
3331 }
3332
3333#endif
3334
3335 return _dbus_connection_send_and_unlock (connection,
3336 message,
3337 serial);
3338}
3339
3340static dbus_bool_t
3341reply_handler_timeout (void *data)
3342{
3343 DBusConnection *connection;
3344 DBusDispatchStatus status;
3345 DBusPendingCall *pending = data;
3346
3347 connection = _dbus_pending_call_get_connection_and_lock (pending);
3348 _dbus_connection_ref_unlocked (connection);
3349
3351 connection);
3355
3356 _dbus_verbose ("middle\n");
3357 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3358
3359 /* Unlocks, and calls out to user code */
3360 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3361 dbus_connection_unref (connection);
3362
3363 return TRUE;
3364}
3365
3410 DBusMessage *message,
3411 DBusPendingCall **pending_return,
3412 int timeout_milliseconds)
3413{
3414 DBusPendingCall *pending;
3415 dbus_int32_t serial = -1;
3416 DBusDispatchStatus status;
3417
3418 _dbus_return_val_if_fail (connection != NULL, FALSE);
3419 _dbus_return_val_if_fail (message != NULL, FALSE);
3420 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3421
3422 if (pending_return)
3423 *pending_return = NULL;
3424
3425 CONNECTION_LOCK (connection);
3426
3427#ifdef HAVE_UNIX_FD_PASSING
3428
3429 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3430 message->n_unix_fds > 0)
3431 {
3432 /* Refuse to send fds on a connection that cannot handle
3433 them. Unfortunately we cannot return a proper error here, so
3434 the best we can do is return TRUE but leave *pending_return
3435 as NULL. */
3436 CONNECTION_UNLOCK (connection);
3437 return TRUE;
3438 }
3439
3440#endif
3441
3442 if (!_dbus_connection_get_is_connected_unlocked (connection))
3443 {
3444 CONNECTION_UNLOCK (connection);
3445
3446 return TRUE;
3447 }
3448
3449 pending = _dbus_pending_call_new_unlocked (connection,
3450 timeout_milliseconds,
3451 reply_handler_timeout);
3452
3453 if (pending == NULL)
3454 {
3455 CONNECTION_UNLOCK (connection);
3456 return FALSE;
3457 }
3458
3459 /* Assign a serial to the message */
3460 serial = dbus_message_get_serial (message);
3461 if (serial == 0)
3462 {
3463 serial = _dbus_connection_get_next_client_serial (connection);
3464 dbus_message_set_serial (message, serial);
3465 }
3466
3467 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
3468 goto error;
3469
3470 /* Insert the serial in the pending replies hash;
3471 * hash takes a refcount on DBusPendingCall.
3472 * Also, add the timeout.
3473 */
3474 if (!_dbus_connection_attach_pending_call_unlocked (connection,
3475 pending))
3476 goto error;
3477
3478 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
3479 {
3480 _dbus_connection_detach_pending_call_and_unlock (connection,
3481 pending);
3482 goto error_unlocked;
3483 }
3484
3485 if (pending_return)
3486 *pending_return = pending; /* hand off refcount */
3487 else
3488 {
3489 _dbus_connection_detach_pending_call_unlocked (connection, pending);
3490 /* we still have a ref to the pending call in this case, we unref
3491 * after unlocking, below
3492 */
3493 }
3494
3495 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3496
3497 /* this calls out to user code */
3498 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3499
3500 if (pending_return == NULL)
3501 dbus_pending_call_unref (pending);
3502
3503 return TRUE;
3504
3505 error:
3506 CONNECTION_UNLOCK (connection);
3507 error_unlocked:
3508 dbus_pending_call_unref (pending);
3509 return FALSE;
3510}
3511
3546 DBusMessage *message,
3547 int timeout_milliseconds,
3548 DBusError *error)
3549{
3550 DBusMessage *reply;
3551 DBusPendingCall *pending;
3552
3553 _dbus_return_val_if_fail (connection != NULL, NULL);
3554 _dbus_return_val_if_fail (message != NULL, NULL);
3555 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
3556 _dbus_return_val_if_error_is_set (error, NULL);
3557
3558#ifdef HAVE_UNIX_FD_PASSING
3559
3560 CONNECTION_LOCK (connection);
3561 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3562 message->n_unix_fds > 0)
3563 {
3564 CONNECTION_UNLOCK (connection);
3565 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
3566 return NULL;
3567 }
3568 CONNECTION_UNLOCK (connection);
3569
3570#endif
3571
3572 if (!dbus_connection_send_with_reply (connection, message,
3573 &pending, timeout_milliseconds))
3574 {
3575 _DBUS_SET_OOM (error);
3576 return NULL;
3577 }
3578
3579 if (pending == NULL)
3580 {
3581 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
3582 return NULL;
3583 }
3584
3585 dbus_pending_call_block (pending);
3586
3587 reply = dbus_pending_call_steal_reply (pending);
3588 dbus_pending_call_unref (pending);
3589
3590 /* call_complete_and_unlock() called from pending_call_block() should
3591 * always fill this in.
3592 */
3593 _dbus_assert (reply != NULL);
3594
3595 if (dbus_set_error_from_message (error, reply))
3596 {
3597 dbus_message_unref (reply);
3598 return NULL;
3599 }
3600 else
3601 return reply;
3602}
3603
3612static DBusDispatchStatus
3613_dbus_connection_flush_unlocked (DBusConnection *connection)
3614{
3615 /* We have to specify DBUS_ITERATION_DO_READING here because
3616 * otherwise we could have two apps deadlock if they are both doing
3617 * a flush(), and the kernel buffers fill up. This could change the
3618 * dispatch status.
3619 */
3620 DBusDispatchStatus status;
3621
3622 HAVE_LOCK_CHECK (connection);
3623
3624 while (connection->n_outgoing > 0 &&
3625 _dbus_connection_get_is_connected_unlocked (connection))
3626 {
3627 _dbus_verbose ("doing iteration in\n");
3628 HAVE_LOCK_CHECK (connection);
3630 NULL,
3631 DBUS_ITERATION_DO_READING |
3632 DBUS_ITERATION_DO_WRITING |
3633 DBUS_ITERATION_BLOCK,
3634 -1);
3635 }
3636
3637 HAVE_LOCK_CHECK (connection);
3638 _dbus_verbose ("middle\n");
3639 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3640
3641 HAVE_LOCK_CHECK (connection);
3642 return status;
3643}
3644
3650void
3652{
3653 /* We have to specify DBUS_ITERATION_DO_READING here because
3654 * otherwise we could have two apps deadlock if they are both doing
3655 * a flush(), and the kernel buffers fill up. This could change the
3656 * dispatch status.
3657 */
3658 DBusDispatchStatus status;
3659
3660 _dbus_return_if_fail (connection != NULL);
3661
3662 CONNECTION_LOCK (connection);
3663
3664 status = _dbus_connection_flush_unlocked (connection);
3665
3666 HAVE_LOCK_CHECK (connection);
3667 /* Unlocks and calls out to user code */
3668 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3669
3670 _dbus_verbose ("end\n");
3671}
3672
3683static dbus_bool_t
3684_dbus_connection_read_write_dispatch (DBusConnection *connection,
3685 int timeout_milliseconds,
3686 dbus_bool_t dispatch)
3687{
3688 DBusDispatchStatus dstatus;
3689 dbus_bool_t progress_possible;
3690
3691 /* Need to grab a ref here in case we're a private connection and
3692 * the user drops the last ref in a handler we call; see bug
3693 * https://bugs.freedesktop.org/show_bug.cgi?id=15635
3694 */
3695 dbus_connection_ref (connection);
3696 dstatus = dbus_connection_get_dispatch_status (connection);
3697
3698 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
3699 {
3700 _dbus_verbose ("doing dispatch\n");
3701 dbus_connection_dispatch (connection);
3702 CONNECTION_LOCK (connection);
3703 }
3704 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
3705 {
3706 _dbus_verbose ("pausing for memory\n");
3707 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
3708 CONNECTION_LOCK (connection);
3709 }
3710 else
3711 {
3712 CONNECTION_LOCK (connection);
3713 if (_dbus_connection_get_is_connected_unlocked (connection))
3714 {
3715 _dbus_verbose ("doing iteration\n");
3717 NULL,
3718 DBUS_ITERATION_DO_READING |
3719 DBUS_ITERATION_DO_WRITING |
3720 DBUS_ITERATION_BLOCK,
3721 timeout_milliseconds);
3722 }
3723 }
3724
3725 HAVE_LOCK_CHECK (connection);
3726 /* If we can dispatch, we can make progress until the Disconnected message
3727 * has been processed; if we can only read/write, we can make progress
3728 * as long as the transport is open.
3729 */
3730 if (dispatch)
3731 progress_possible = connection->n_incoming != 0 ||
3732 connection->disconnect_message_link != NULL;
3733 else
3734 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
3735
3736 CONNECTION_UNLOCK (connection);
3737
3738 dbus_connection_unref (connection);
3739
3740 return progress_possible; /* TRUE if we can make more progress */
3741}
3742
3743
3780 int timeout_milliseconds)
3781{
3782 _dbus_return_val_if_fail (connection != NULL, FALSE);
3783 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3784 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
3785}
3786
3812 int timeout_milliseconds)
3813{
3814 _dbus_return_val_if_fail (connection != NULL, FALSE);
3815 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3816 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
3817}
3818
3819/* We need to call this anytime we pop the head of the queue, and then
3820 * update_dispatch_status_and_unlock needs to be called afterward
3821 * which will "process" the disconnected message and set
3822 * disconnected_message_processed.
3823 */
3824static void
3825check_disconnected_message_arrived_unlocked (DBusConnection *connection,
3826 DBusMessage *head_of_queue)
3827{
3828 HAVE_LOCK_CHECK (connection);
3829
3830 /* checking that the link is NULL is an optimization to avoid the is_signal call */
3831 if (connection->disconnect_message_link == NULL &&
3832 dbus_message_is_signal (head_of_queue,
3834 "Disconnected"))
3835 {
3836 connection->disconnected_message_arrived = TRUE;
3837 }
3838}
3839
3861{
3862 DBusDispatchStatus status;
3863 DBusMessage *message;
3864
3865 _dbus_return_val_if_fail (connection != NULL, NULL);
3866
3867 _dbus_verbose ("start\n");
3868
3869 /* this is called for the side effect that it queues
3870 * up any messages from the transport
3871 */
3872 status = dbus_connection_get_dispatch_status (connection);
3873 if (status != DBUS_DISPATCH_DATA_REMAINS)
3874 return NULL;
3875
3876 CONNECTION_LOCK (connection);
3877
3878 _dbus_connection_acquire_dispatch (connection);
3879
3880 /* While a message is outstanding, the dispatch lock is held */
3881 _dbus_assert (connection->message_borrowed == NULL);
3882
3883 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
3884
3885 message = connection->message_borrowed;
3886
3887 check_disconnected_message_arrived_unlocked (connection, message);
3888
3889 /* Note that we KEEP the dispatch lock until the message is returned */
3890 if (message == NULL)
3891 _dbus_connection_release_dispatch (connection);
3892
3893 CONNECTION_UNLOCK (connection);
3894
3895 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
3896
3897 /* We don't update dispatch status until it's returned or stolen */
3898
3899 return message;
3900}
3901
3910void
3912 DBusMessage *message)
3913{
3914 DBusDispatchStatus status;
3915
3916 _dbus_return_if_fail (connection != NULL);
3917 _dbus_return_if_fail (message != NULL);
3918 _dbus_return_if_fail (message == connection->message_borrowed);
3919 _dbus_return_if_fail (connection->dispatch_acquired);
3920
3921 CONNECTION_LOCK (connection);
3922
3923 _dbus_assert (message == connection->message_borrowed);
3924
3925 connection->message_borrowed = NULL;
3926
3927 _dbus_connection_release_dispatch (connection);
3928
3929 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3930 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3931
3932 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
3933}
3934
3944void
3946 DBusMessage *message)
3947{
3948 DBusMessage *pop_message;
3949 DBusDispatchStatus status;
3950
3951 _dbus_return_if_fail (connection != NULL);
3952 _dbus_return_if_fail (message != NULL);
3953 _dbus_return_if_fail (message == connection->message_borrowed);
3954 _dbus_return_if_fail (connection->dispatch_acquired);
3955
3956 CONNECTION_LOCK (connection);
3957
3958 _dbus_assert (message == connection->message_borrowed);
3959
3960 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
3961 _dbus_assert (message == pop_message);
3962 (void) pop_message; /* unused unless asserting */
3963
3964 connection->n_incoming -= 1;
3965
3966 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
3967 message, connection->n_incoming);
3968
3969 connection->message_borrowed = NULL;
3970
3971 _dbus_connection_release_dispatch (connection);
3972
3973 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3974 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3975 _dbus_message_trace_ref (message, -1, -1,
3976 "dbus_connection_steal_borrowed_message");
3977}
3978
3979/* See dbus_connection_pop_message, but requires the caller to own
3980 * the lock before calling. May drop the lock while running.
3981 */
3982static DBusList*
3983_dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
3984{
3985 HAVE_LOCK_CHECK (connection);
3986
3987 _dbus_assert (connection->message_borrowed == NULL);
3988
3989 if (connection->n_incoming > 0)
3990 {
3991 DBusList *link;
3992
3993 link = _dbus_list_pop_first_link (&connection->incoming_messages);
3994 connection->n_incoming -= 1;
3995
3996 _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
3997 link->data,
3999 dbus_message_get_path (link->data) ?
4000 dbus_message_get_path (link->data) :
4001 "no path",
4004 "no interface",
4007 "no member",
4010 connection, connection->n_incoming);
4011
4012 _dbus_message_trace_ref (link->data, -1, -1,
4013 "_dbus_connection_pop_message_link_unlocked");
4014
4015 check_disconnected_message_arrived_unlocked (connection, link->data);
4016
4017 return link;
4018 }
4019 else
4020 return NULL;
4021}
4022
4023/* See dbus_connection_pop_message, but requires the caller to own
4024 * the lock before calling. May drop the lock while running.
4025 */
4026static DBusMessage*
4027_dbus_connection_pop_message_unlocked (DBusConnection *connection)
4028{
4029 DBusList *link;
4030
4031 HAVE_LOCK_CHECK (connection);
4032
4033 link = _dbus_connection_pop_message_link_unlocked (connection);
4034
4035 if (link != NULL)
4036 {
4037 DBusMessage *message;
4038
4039 message = link->data;
4040
4041 _dbus_list_free_link (link);
4042
4043 return message;
4044 }
4045 else
4046 return NULL;
4047}
4048
4049static void
4050_dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
4051 DBusList *message_link)
4052{
4053 HAVE_LOCK_CHECK (connection);
4054
4055 _dbus_assert (message_link != NULL);
4056 /* You can't borrow a message while a link is outstanding */
4057 _dbus_assert (connection->message_borrowed == NULL);
4058 /* We had to have the dispatch lock across the pop/putback */
4059 _dbus_assert (connection->dispatch_acquired);
4060
4062 message_link);
4063 connection->n_incoming += 1;
4064
4065 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
4066 message_link->data,
4068 dbus_message_get_interface (message_link->data) ?
4069 dbus_message_get_interface (message_link->data) :
4070 "no interface",
4071 dbus_message_get_member (message_link->data) ?
4072 dbus_message_get_member (message_link->data) :
4073 "no member",
4074 dbus_message_get_signature (message_link->data),
4075 connection, connection->n_incoming);
4076
4077 _dbus_message_trace_ref (message_link->data, -1, -1,
4078 "_dbus_connection_putback_message_link_unlocked");
4079}
4080
4102{
4103 DBusMessage *message;
4104 DBusDispatchStatus status;
4105
4106 _dbus_verbose ("start\n");
4107
4108 /* this is called for the side effect that it queues
4109 * up any messages from the transport
4110 */
4111 status = dbus_connection_get_dispatch_status (connection);
4112 if (status != DBUS_DISPATCH_DATA_REMAINS)
4113 return NULL;
4114
4115 CONNECTION_LOCK (connection);
4116 _dbus_connection_acquire_dispatch (connection);
4117 HAVE_LOCK_CHECK (connection);
4118
4119 message = _dbus_connection_pop_message_unlocked (connection);
4120
4121 _dbus_verbose ("Returning popped message %p\n", message);
4122
4123 _dbus_connection_release_dispatch (connection);
4124
4125 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4126 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4127
4128 return message;
4129}
4130
4138static void
4139_dbus_connection_acquire_dispatch (DBusConnection *connection)
4140{
4141 HAVE_LOCK_CHECK (connection);
4142
4143 _dbus_connection_ref_unlocked (connection);
4144 CONNECTION_UNLOCK (connection);
4145
4146 _dbus_verbose ("locking dispatch_mutex\n");
4147 _dbus_cmutex_lock (connection->dispatch_mutex);
4148
4149 while (connection->dispatch_acquired)
4150 {
4151 _dbus_verbose ("waiting for dispatch to be acquirable\n");
4152 _dbus_condvar_wait (connection->dispatch_cond,
4153 connection->dispatch_mutex);
4154 }
4155
4156 _dbus_assert (!connection->dispatch_acquired);
4157
4158 connection->dispatch_acquired = TRUE;
4159
4160 _dbus_verbose ("unlocking dispatch_mutex\n");
4161 _dbus_cmutex_unlock (connection->dispatch_mutex);
4162
4163 CONNECTION_LOCK (connection);
4165}
4166
4174static void
4175_dbus_connection_release_dispatch (DBusConnection *connection)
4176{
4177 HAVE_LOCK_CHECK (connection);
4178
4179 _dbus_verbose ("locking dispatch_mutex\n");
4180 _dbus_cmutex_lock (connection->dispatch_mutex);
4181
4182 _dbus_assert (connection->dispatch_acquired);
4183
4184 connection->dispatch_acquired = FALSE;
4186
4187 _dbus_verbose ("unlocking dispatch_mutex\n");
4188 _dbus_cmutex_unlock (connection->dispatch_mutex);
4189}
4190
4191static void
4192_dbus_connection_failed_pop (DBusConnection *connection,
4193 DBusList *message_link)
4194{
4196 message_link);
4197 connection->n_incoming += 1;
4198}
4199
4200/* Note this may be called multiple times since we don't track whether we already did it */
4201static void
4202notify_disconnected_unlocked (DBusConnection *connection)
4203{
4204 HAVE_LOCK_CHECK (connection);
4205
4206 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
4207 * connection from dbus_bus_get(). We make the same guarantee for
4208 * dbus_connection_open() but in a different way since we don't want to
4209 * unref right here; we instead check for connectedness before returning
4210 * the connection from the hash.
4211 */
4213
4214 /* Dump the outgoing queue, we aren't going to be able to
4215 * send it now, and we'd like accessors like
4216 * dbus_connection_get_outgoing_size() to be accurate.
4217 */
4218 if (connection->n_outgoing > 0)
4219 {
4220 DBusList *link;
4221
4222 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
4223 connection->n_outgoing);
4224
4225 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
4226 {
4227 _dbus_connection_message_sent_unlocked (connection, link->data);
4228 }
4229 }
4230}
4231
4232/* Note this may be called multiple times since we don't track whether we already did it */
4233static DBusDispatchStatus
4234notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
4235{
4236 HAVE_LOCK_CHECK (connection);
4237
4238 if (connection->disconnect_message_link != NULL)
4239 {
4240 _dbus_verbose ("Sending disconnect message\n");
4241
4242 /* If we have pending calls, queue their timeouts - we want the Disconnected
4243 * to be the last message, after these timeouts.
4244 */
4245 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
4246
4247 /* We haven't sent the disconnect message already,
4248 * and all real messages have been queued up.
4249 */
4251 connection->disconnect_message_link);
4252 connection->disconnect_message_link = NULL;
4253
4255 }
4256
4258}
4259
4260static DBusDispatchStatus
4261_dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
4262{
4263 HAVE_LOCK_CHECK (connection);
4264
4265 if (connection->n_incoming > 0)
4267 else if (!_dbus_transport_queue_messages (connection->transport))
4269 else
4270 {
4271 DBusDispatchStatus status;
4272 dbus_bool_t is_connected;
4273
4274 status = _dbus_transport_get_dispatch_status (connection->transport);
4275 is_connected = _dbus_transport_get_is_connected (connection->transport);
4276
4277 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
4278 DISPATCH_STATUS_NAME (status), is_connected);
4279
4280 if (!is_connected)
4281 {
4282 /* It's possible this would be better done by having an explicit
4283 * notification from _dbus_transport_disconnect() that would
4284 * synchronously do this, instead of waiting for the next dispatch
4285 * status check. However, probably not good to change until it causes
4286 * a problem.
4287 */
4288 notify_disconnected_unlocked (connection);
4289
4290 /* I'm not sure this is needed; the idea is that we want to
4291 * queue the Disconnected only after we've read all the
4292 * messages, but if we're disconnected maybe we are guaranteed
4293 * to have read them all ?
4294 */
4295 if (status == DBUS_DISPATCH_COMPLETE)
4296 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
4297 }
4298
4299 if (status != DBUS_DISPATCH_COMPLETE)
4300 return status;
4301 else if (connection->n_incoming > 0)
4303 else
4305 }
4306}
4307
4308static void
4309_dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
4310 DBusDispatchStatus new_status)
4311{
4312 dbus_bool_t changed;
4314 void *data;
4315
4316 HAVE_LOCK_CHECK (connection);
4317
4318 _dbus_connection_ref_unlocked (connection);
4319
4320 changed = new_status != connection->last_dispatch_status;
4321
4322 connection->last_dispatch_status = new_status;
4323
4324 function = connection->dispatch_status_function;
4325 data = connection->dispatch_status_data;
4326
4327 if (connection->disconnected_message_arrived &&
4328 !connection->disconnected_message_processed)
4329 {
4331
4332 /* this does an unref, but we have a ref
4333 * so we should not run the finalizer here
4334 * inside the lock.
4335 */
4336 connection_forget_shared_unlocked (connection);
4337
4338 if (connection->exit_on_disconnect)
4339 {
4340 CONNECTION_UNLOCK (connection);
4341
4342 _dbus_verbose ("Exiting on Disconnected signal\n");
4343 _dbus_exit (1);
4344 _dbus_assert_not_reached ("Call to exit() returned");
4345 }
4346 }
4347
4348 /* We drop the lock */
4349 CONNECTION_UNLOCK (connection);
4350
4351 if (changed && function)
4352 {
4353 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
4354 connection, new_status,
4355 DISPATCH_STATUS_NAME (new_status));
4356 (* function) (connection, new_status, data);
4357 }
4358
4359 dbus_connection_unref (connection);
4360}
4361
4389{
4390 DBusDispatchStatus status;
4391
4392 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4393
4394 _dbus_verbose ("start\n");
4395
4396 CONNECTION_LOCK (connection);
4397
4398 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4399
4400 CONNECTION_UNLOCK (connection);
4401
4402 return status;
4403}
4404
4408static DBusHandlerResult
4409_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
4410 DBusMessage *message)
4411{
4412 dbus_bool_t sent = FALSE;
4413 DBusMessage *ret = NULL;
4414 DBusList *expire_link;
4415
4416 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
4417 {
4418 /* This means we're letting the bus route this message */
4420 }
4421
4423 {
4425 }
4426
4427 /* Preallocate a linked-list link, so that if we need to dispose of a
4428 * message, we can attach it to the expired list */
4429 expire_link = _dbus_list_alloc_link (NULL);
4430
4431 if (!expire_link)
4433
4434 if (dbus_message_is_method_call (message,
4436 "Ping"))
4437 {
4438 ret = dbus_message_new_method_return (message);
4439 if (ret == NULL)
4440 goto out;
4441
4442 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4443 }
4444 else if (dbus_message_is_method_call (message,
4446 "GetMachineId"))
4447 {
4448 DBusString uuid;
4449 DBusError error = DBUS_ERROR_INIT;
4450
4451 if (!_dbus_string_init (&uuid))
4452 goto out;
4453
4454 if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
4455 {
4456 const char *v_STRING;
4457
4458 ret = dbus_message_new_method_return (message);
4459
4460 if (ret == NULL)
4461 {
4462 _dbus_string_free (&uuid);
4463 goto out;
4464 }
4465
4466 v_STRING = _dbus_string_get_const_data (&uuid);
4467 if (dbus_message_append_args (ret,
4468 DBUS_TYPE_STRING, &v_STRING,
4470 {
4471 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4472 }
4473 }
4474 else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
4475 {
4476 dbus_error_free (&error);
4477 goto out;
4478 }
4479 else
4480 {
4481 ret = dbus_message_new_error (message, error.name, error.message);
4482 dbus_error_free (&error);
4483
4484 if (ret == NULL)
4485 goto out;
4486
4487 sent = _dbus_connection_send_unlocked_no_update (connection, ret,
4488 NULL);
4489 }
4490
4491 _dbus_string_free (&uuid);
4492 }
4493 else
4494 {
4495 /* We need to bounce anything else with this interface, otherwise apps
4496 * could start extending the interface and when we added extensions
4497 * here to DBusConnection we'd break those apps.
4498 */
4499 ret = dbus_message_new_error (message,
4501 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
4502 if (ret == NULL)
4503 goto out;
4504
4505 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4506 }
4507
4508out:
4509 if (ret == NULL)
4510 {
4511 _dbus_list_free_link (expire_link);
4512 }
4513 else
4514 {
4515 /* It'll be safe to unref the reply when we unlock */
4516 expire_link->data = ret;
4517 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4518 }
4519
4520 if (!sent)
4522
4524}
4525
4532static DBusHandlerResult
4533_dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
4534 DBusMessage *message)
4535{
4536 /* We just run one filter for now but have the option to run more
4537 if the spec calls for it in the future */
4538
4539 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
4540}
4541
4586{
4587 DBusMessage *message;
4588 DBusList *link, *filter_list_copy, *message_link;
4589 DBusHandlerResult result;
4590 DBusPendingCall *pending;
4591 dbus_int32_t reply_serial;
4592 DBusDispatchStatus status;
4593 dbus_bool_t found_object;
4594
4595 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4596
4597 _dbus_verbose ("\n");
4598
4599 CONNECTION_LOCK (connection);
4600 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4601 if (status != DBUS_DISPATCH_DATA_REMAINS)
4602 {
4603 /* unlocks and calls out to user code */
4604 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4605 return status;
4606 }
4607
4608 /* We need to ref the connection since the callback could potentially
4609 * drop the last ref to it
4610 */
4611 _dbus_connection_ref_unlocked (connection);
4612
4613 _dbus_connection_acquire_dispatch (connection);
4614 HAVE_LOCK_CHECK (connection);
4615
4616 message_link = _dbus_connection_pop_message_link_unlocked (connection);
4617 if (message_link == NULL)
4618 {
4619 /* another thread dispatched our stuff */
4620
4621 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
4622
4623 _dbus_connection_release_dispatch (connection);
4624
4625 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4626
4627 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4628
4629 dbus_connection_unref (connection);
4630
4631 return status;
4632 }
4633
4634 message = message_link->data;
4635
4636 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
4637 message,
4639 dbus_message_get_interface (message) ?
4640 dbus_message_get_interface (message) :
4641 "no interface",
4642 dbus_message_get_member (message) ?
4643 dbus_message_get_member (message) :
4644 "no member",
4645 dbus_message_get_signature (message));
4646
4648
4649 /* Pending call handling must be first, because if you do
4650 * dbus_connection_send_with_reply_and_block() or
4651 * dbus_pending_call_block() then no handlers/filters will be run on
4652 * the reply. We want consistent semantics in the case where we
4653 * dbus_connection_dispatch() the reply.
4654 */
4655
4656 reply_serial = dbus_message_get_reply_serial (message);
4657 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
4658 reply_serial);
4659 if (pending)
4660 {
4661 _dbus_verbose ("Dispatching a pending reply\n");
4662 complete_pending_call_and_unlock (connection, pending, message);
4663 pending = NULL; /* it's probably unref'd */
4664
4665 CONNECTION_LOCK (connection);
4666 _dbus_verbose ("pending call completed in dispatch\n");
4668 goto out;
4669 }
4670
4671 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
4673 goto out;
4674
4675 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
4676 {
4677 _dbus_connection_release_dispatch (connection);
4678 HAVE_LOCK_CHECK (connection);
4679
4680 _dbus_connection_failed_pop (connection, message_link);
4681
4682 /* unlocks and calls user code */
4683 _dbus_connection_update_dispatch_status_and_unlock (connection,
4685 dbus_connection_unref (connection);
4686
4688 }
4689
4690 _dbus_list_foreach (&filter_list_copy,
4691 (DBusForeachFunction)_dbus_message_filter_ref,
4692 NULL);
4693
4694 /* We're still protected from dispatch() reentrancy here
4695 * since we acquired the dispatcher
4696 */
4697 CONNECTION_UNLOCK (connection);
4698
4699 link = _dbus_list_get_first_link (&filter_list_copy);
4700 while (link != NULL)
4701 {
4702 DBusMessageFilter *filter = link->data;
4703 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
4704
4705 if (filter->function == NULL)
4706 {
4707 _dbus_verbose (" filter was removed in a callback function\n");
4708 link = next;
4709 continue;
4710 }
4711
4712 _dbus_verbose (" running filter on message %p\n", message);
4713 result = (* filter->function) (connection, message, filter->user_data);
4714
4716 break;
4717
4718 link = next;
4719 }
4720
4721 _dbus_list_foreach (&filter_list_copy,
4722 (DBusForeachFunction)_dbus_message_filter_unref,
4723 NULL);
4724 _dbus_list_clear (&filter_list_copy);
4725
4726 CONNECTION_LOCK (connection);
4727
4728 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4729 {
4730 _dbus_verbose ("No memory\n");
4731 goto out;
4732 }
4733 else if (result == DBUS_HANDLER_RESULT_HANDLED)
4734 {
4735 _dbus_verbose ("filter handled message in dispatch\n");
4736 goto out;
4737 }
4738
4739 /* We're still protected from dispatch() reentrancy here
4740 * since we acquired the dispatcher
4741 */
4742 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
4743 message,
4745 dbus_message_get_interface (message) ?
4746 dbus_message_get_interface (message) :
4747 "no interface",
4748 dbus_message_get_member (message) ?
4749 dbus_message_get_member (message) :
4750 "no member",
4751 dbus_message_get_signature (message));
4752
4753 HAVE_LOCK_CHECK (connection);
4754 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
4755 message,
4756 &found_object);
4757
4758 CONNECTION_LOCK (connection);
4759
4761 {
4762 _dbus_verbose ("object tree handled message in dispatch\n");
4763 goto out;
4764 }
4765
4767 {
4768 DBusMessage *reply;
4769 DBusString str;
4770 DBusPreallocatedSend *preallocated;
4771 DBusList *expire_link;
4772
4773 _dbus_verbose (" sending error %s\n",
4775
4776 if (!_dbus_string_init (&str))
4777 {
4779 _dbus_verbose ("no memory for error string in dispatch\n");
4780 goto out;
4781 }
4782
4783 if (!_dbus_string_append_printf (&str,
4784 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
4785 dbus_message_get_member (message),
4787 dbus_message_get_interface (message)))
4788 {
4789 _dbus_string_free (&str);
4791 _dbus_verbose ("no memory for error string in dispatch\n");
4792 goto out;
4793 }
4794
4795 reply = dbus_message_new_error (message,
4797 _dbus_string_get_const_data (&str));
4798 _dbus_string_free (&str);
4799
4800 if (reply == NULL)
4801 {
4803 _dbus_verbose ("no memory for error reply in dispatch\n");
4804 goto out;
4805 }
4806
4807 expire_link = _dbus_list_alloc_link (reply);
4808
4809 if (expire_link == NULL)
4810 {
4811 dbus_message_unref (reply);
4813 _dbus_verbose ("no memory for error send in dispatch\n");
4814 goto out;
4815 }
4816
4817 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
4818
4819 if (preallocated == NULL)
4820 {
4821 _dbus_list_free_link (expire_link);
4822 /* It's OK that this is finalized, because it hasn't been seen by
4823 * anything that could attach user callbacks */
4824 dbus_message_unref (reply);
4826 _dbus_verbose ("no memory for error send in dispatch\n");
4827 goto out;
4828 }
4829
4830 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
4831 reply, NULL);
4832 /* reply will be freed when we release the lock */
4833 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4834
4836 }
4837
4838 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
4840 dbus_message_get_interface (message) ?
4841 dbus_message_get_interface (message) :
4842 "no interface",
4843 dbus_message_get_member (message) ?
4844 dbus_message_get_member (message) :
4845 "no member",
4847 connection);
4848
4849 out:
4850 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4851 {
4852 _dbus_verbose ("out of memory\n");
4853
4854 /* Put message back, and we'll start over.
4855 * Yes this means handlers must be idempotent if they
4856 * don't return HANDLED; c'est la vie.
4857 */
4858 _dbus_connection_putback_message_link_unlocked (connection,
4859 message_link);
4860 /* now we don't want to free them */
4861 message_link = NULL;
4862 message = NULL;
4863 }
4864 else
4865 {
4866 _dbus_verbose (" ... done dispatching\n");
4867 }
4868
4869 _dbus_connection_release_dispatch (connection);
4870 HAVE_LOCK_CHECK (connection);
4871
4872 if (message != NULL)
4873 {
4874 /* We don't want this message to count in maximum message limits when
4875 * computing the dispatch status, below. We have to drop the lock
4876 * temporarily, because finalizing a message can trigger callbacks.
4877 *
4878 * We have a reference to the connection, and we don't use any cached
4879 * pointers to the connection's internals below this point, so it should
4880 * be safe to drop the lock and take it back. */
4881 CONNECTION_UNLOCK (connection);
4882 dbus_message_unref (message);
4883 CONNECTION_LOCK (connection);
4884 }
4885
4886 if (message_link != NULL)
4887 _dbus_list_free_link (message_link);
4888
4889 _dbus_verbose ("before final status update\n");
4890 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4891
4892 /* unlocks and calls user code */
4893 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4894
4895 dbus_connection_unref (connection);
4896
4897 return status;
4898}
4899
4963 DBusAddWatchFunction add_function,
4964 DBusRemoveWatchFunction remove_function,
4965 DBusWatchToggledFunction toggled_function,
4966 void *data,
4967 DBusFreeFunction free_data_function)
4968{
4969 dbus_bool_t retval;
4970
4971 _dbus_return_val_if_fail (connection != NULL, FALSE);
4972
4973 CONNECTION_LOCK (connection);
4974
4975 retval = _dbus_watch_list_set_functions (connection->watches,
4976 add_function, remove_function,
4977 toggled_function,
4978 data, free_data_function);
4979
4980 CONNECTION_UNLOCK (connection);
4981
4982 return retval;
4983}
4984
5026 DBusAddTimeoutFunction add_function,
5027 DBusRemoveTimeoutFunction remove_function,
5028 DBusTimeoutToggledFunction toggled_function,
5029 void *data,
5030 DBusFreeFunction free_data_function)
5031{
5032 dbus_bool_t retval;
5033
5034 _dbus_return_val_if_fail (connection != NULL, FALSE);
5035
5036 CONNECTION_LOCK (connection);
5037
5038 retval = _dbus_timeout_list_set_functions (connection->timeouts,
5039 add_function, remove_function,
5040 toggled_function,
5041 data, free_data_function);
5042
5043 CONNECTION_UNLOCK (connection);
5044
5045 return retval;
5046}
5047
5062void
5064 DBusWakeupMainFunction wakeup_main_function,
5065 void *data,
5066 DBusFreeFunction free_data_function)
5067{
5068 void *old_data;
5069 DBusFreeFunction old_free_data;
5070
5071 _dbus_return_if_fail (connection != NULL);
5072
5073 CONNECTION_LOCK (connection);
5074 old_data = connection->wakeup_main_data;
5075 old_free_data = connection->free_wakeup_main_data;
5076
5077 connection->wakeup_main_function = wakeup_main_function;
5078 connection->wakeup_main_data = data;
5079 connection->free_wakeup_main_data = free_data_function;
5080
5081 CONNECTION_UNLOCK (connection);
5082
5083 /* Callback outside the lock */
5084 if (old_free_data)
5085 (*old_free_data) (old_data);
5086}
5087
5108void
5111 void *data,
5112 DBusFreeFunction free_data_function)
5113{
5114 void *old_data;
5115 DBusFreeFunction old_free_data;
5116
5117 _dbus_return_if_fail (connection != NULL);
5118
5119 CONNECTION_LOCK (connection);
5120 old_data = connection->dispatch_status_data;
5121 old_free_data = connection->free_dispatch_status_data;
5122
5123 connection->dispatch_status_function = function;
5124 connection->dispatch_status_data = data;
5125 connection->free_dispatch_status_data = free_data_function;
5126
5127 CONNECTION_UNLOCK (connection);
5128
5129 /* Callback outside the lock */
5130 if (old_free_data)
5131 (*old_free_data) (old_data);
5132}
5133
5155 int *fd)
5156{
5157 _dbus_return_val_if_fail (connection != NULL, FALSE);
5158 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5159
5160#ifdef DBUS_WIN
5161 /* FIXME do this on a lower level */
5162 return FALSE;
5163#endif
5164
5165 return dbus_connection_get_socket(connection, fd);
5166}
5167
5185 int *fd)
5186{
5187 dbus_bool_t retval;
5188 DBusSocket s = DBUS_SOCKET_INIT;
5189
5190 _dbus_return_val_if_fail (connection != NULL, FALSE);
5191 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5192
5193 CONNECTION_LOCK (connection);
5194
5195 retval = _dbus_transport_get_socket_fd (connection->transport, &s);
5196
5197 if (retval)
5198 {
5199 *fd = _dbus_socket_get_int (s);
5200 }
5201
5202 CONNECTION_UNLOCK (connection);
5203
5204 return retval;
5205}
5206
5207
5232 unsigned long *uid)
5233{
5234 dbus_bool_t result;
5235
5236 _dbus_return_val_if_fail (connection != NULL, FALSE);
5237 _dbus_return_val_if_fail (uid != NULL, FALSE);
5238
5239 CONNECTION_LOCK (connection);
5240
5242 result = FALSE;
5243 else
5244 result = _dbus_transport_get_unix_user (connection->transport,
5245 uid);
5246
5247#ifdef DBUS_WIN
5248 _dbus_assert (!result);
5249#endif
5250
5251 CONNECTION_UNLOCK (connection);
5252
5253 return result;
5254}
5255
5268 unsigned long *pid)
5269{
5270 dbus_bool_t result;
5271
5272 _dbus_return_val_if_fail (connection != NULL, FALSE);
5273 _dbus_return_val_if_fail (pid != NULL, FALSE);
5274
5275 CONNECTION_LOCK (connection);
5276
5278 result = FALSE;
5279 else
5280 result = _dbus_transport_get_unix_process_id (connection->transport,
5281 pid);
5282
5283 CONNECTION_UNLOCK (connection);
5284
5285 return result;
5286}
5287
5301 void **data,
5302 dbus_int32_t *data_size)
5303{
5304 dbus_bool_t result;
5305
5306 _dbus_return_val_if_fail (connection != NULL, FALSE);
5307 _dbus_return_val_if_fail (data != NULL, FALSE);
5308 _dbus_return_val_if_fail (data_size != NULL, FALSE);
5309
5310 CONNECTION_LOCK (connection);
5311
5313 result = FALSE;
5314 else
5316 data,
5317 data_size);
5318 CONNECTION_UNLOCK (connection);
5319
5320 return result;
5321}
5322
5345void
5348 void *data,
5349 DBusFreeFunction free_data_function)
5350{
5351 void *old_data = NULL;
5352 DBusFreeFunction old_free_function = NULL;
5353
5354 _dbus_return_if_fail (connection != NULL);
5355
5356 CONNECTION_LOCK (connection);
5358 function, data, free_data_function,
5359 &old_data, &old_free_function);
5360 CONNECTION_UNLOCK (connection);
5361
5362 if (old_free_function != NULL)
5363 (* old_free_function) (old_data);
5364}
5365
5366/* Same calling convention as dbus_connection_get_windows_user */
5368_dbus_connection_get_linux_security_label (DBusConnection *connection,
5369 char **label_p)
5370{
5371 dbus_bool_t result;
5372
5373 _dbus_assert (connection != NULL);
5374 _dbus_assert (label_p != NULL);
5375
5376 CONNECTION_LOCK (connection);
5377
5379 result = FALSE;
5380 else
5381 result = _dbus_transport_get_linux_security_label (connection->transport,
5382 label_p);
5383#ifndef __linux__
5384 _dbus_assert (!result);
5385#endif
5386
5387 CONNECTION_UNLOCK (connection);
5388
5389 return result;
5390}
5391
5425 char **windows_sid_p)
5426{
5427 dbus_bool_t result;
5428
5429 _dbus_return_val_if_fail (connection != NULL, FALSE);
5430 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
5431
5432 CONNECTION_LOCK (connection);
5433
5435 result = FALSE;
5436 else
5437 result = _dbus_transport_get_windows_user (connection->transport,
5438 windows_sid_p);
5439
5440#ifdef DBUS_UNIX
5441 _dbus_assert (!result);
5442#endif
5443
5444 CONNECTION_UNLOCK (connection);
5445
5446 return result;
5447}
5448
5470void
5473 void *data,
5474 DBusFreeFunction free_data_function)
5475{
5476 void *old_data = NULL;
5477 DBusFreeFunction old_free_function = NULL;
5478
5479 _dbus_return_if_fail (connection != NULL);
5480
5481 CONNECTION_LOCK (connection);
5483 function, data, free_data_function,
5484 &old_data, &old_free_function);
5485 CONNECTION_UNLOCK (connection);
5486
5487 if (old_free_function != NULL)
5488 (* old_free_function) (old_data);
5489}
5490
5517void
5519 dbus_bool_t value)
5520{
5521 _dbus_return_if_fail (connection != NULL);
5522
5523 CONNECTION_LOCK (connection);
5525 CONNECTION_UNLOCK (connection);
5526}
5527
5545void
5547 dbus_bool_t value)
5548{
5549 _dbus_return_if_fail (connection != NULL);
5550
5551 CONNECTION_LOCK (connection);
5552 connection->route_peer_messages = value;
5553 CONNECTION_UNLOCK (connection);
5554}
5555
5580 void *user_data,
5581 DBusFreeFunction free_data_function)
5582{
5583 DBusMessageFilter *filter;
5584
5585 _dbus_return_val_if_fail (connection != NULL, FALSE);
5586 _dbus_return_val_if_fail (function != NULL, FALSE);
5587
5588 filter = dbus_new0 (DBusMessageFilter, 1);
5589 if (filter == NULL)
5590 return FALSE;
5591
5592 _dbus_atomic_inc (&filter->refcount);
5593
5594 CONNECTION_LOCK (connection);
5595
5596 if (!_dbus_list_append (&connection->filter_list,
5597 filter))
5598 {
5599 _dbus_message_filter_unref (filter);
5600 CONNECTION_UNLOCK (connection);
5601 return FALSE;
5602 }
5603
5604 /* Fill in filter after all memory allocated,
5605 * so we don't run the free_user_data_function
5606 * if the add_filter() fails
5607 */
5608
5609 filter->function = function;
5610 filter->user_data = user_data;
5611 filter->free_user_data_function = free_data_function;
5612
5613 CONNECTION_UNLOCK (connection);
5614 return TRUE;
5615}
5616
5629void
5632 void *user_data)
5633{
5634 DBusList *link;
5635 DBusMessageFilter *filter;
5636
5637 _dbus_return_if_fail (connection != NULL);
5638 _dbus_return_if_fail (function != NULL);
5639
5640 CONNECTION_LOCK (connection);
5641
5642 filter = NULL;
5643
5644 link = _dbus_list_get_last_link (&connection->filter_list);
5645 while (link != NULL)
5646 {
5647 filter = link->data;
5648
5649 if (filter->function == function &&
5650 filter->user_data == user_data)
5651 {
5652 _dbus_list_remove_link (&connection->filter_list, link);
5653 filter->function = NULL;
5654
5655 break;
5656 }
5657
5658 link = _dbus_list_get_prev_link (&connection->filter_list, link);
5659 filter = NULL;
5660 }
5661
5662 CONNECTION_UNLOCK (connection);
5663
5664#ifndef DBUS_DISABLE_CHECKS
5665 if (filter == NULL)
5666 {
5667 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
5668 function, user_data);
5669 return;
5670 }
5671#endif
5672
5673 /* Call application code */
5674 if (filter->free_user_data_function)
5675 (* filter->free_user_data_function) (filter->user_data);
5676
5677 filter->free_user_data_function = NULL;
5678 filter->user_data = NULL;
5679
5680 _dbus_message_filter_unref (filter);
5681}
5682
5698static dbus_bool_t
5699_dbus_connection_register_object_path (DBusConnection *connection,
5700 dbus_bool_t fallback,
5701 const char *path,
5702 const DBusObjectPathVTable *vtable,
5703 void *user_data,
5704 DBusError *error)
5705{
5706 char **decomposed_path;
5707 dbus_bool_t retval;
5708
5709 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5710 return FALSE;
5711
5712 CONNECTION_LOCK (connection);
5713
5714 retval = _dbus_object_tree_register (connection->objects,
5715 fallback,
5716 (const char **) decomposed_path, vtable,
5717 user_data, error);
5718
5719 CONNECTION_UNLOCK (connection);
5720
5721 dbus_free_string_array (decomposed_path);
5722
5723 return retval;
5724}
5725
5740 const char *path,
5741 const DBusObjectPathVTable *vtable,
5742 void *user_data,
5743 DBusError *error)
5744{
5745 _dbus_return_val_if_fail (connection != NULL, FALSE);
5746 _dbus_return_val_if_fail (path != NULL, FALSE);
5747 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5748 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5749
5750 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
5751}
5752
5770 const char *path,
5771 const DBusObjectPathVTable *vtable,
5772 void *user_data)
5773{
5774 dbus_bool_t retval;
5775 DBusError error = DBUS_ERROR_INIT;
5776
5777 _dbus_return_val_if_fail (connection != NULL, FALSE);
5778 _dbus_return_val_if_fail (path != NULL, FALSE);
5779 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5780 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5781
5782 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
5783
5785 {
5786 _dbus_warn ("%s", error.message);
5787 dbus_error_free (&error);
5788 return FALSE;
5789 }
5790
5791 return retval;
5792}
5793
5810 const char *path,
5811 const DBusObjectPathVTable *vtable,
5812 void *user_data,
5813 DBusError *error)
5814{
5815 _dbus_return_val_if_fail (connection != NULL, FALSE);
5816 _dbus_return_val_if_fail (path != NULL, FALSE);
5817 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5818 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5819
5820 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
5821}
5822
5842 const char *path,
5843 const DBusObjectPathVTable *vtable,
5844 void *user_data)
5845{
5846 dbus_bool_t retval;
5847 DBusError error = DBUS_ERROR_INIT;
5848
5849 _dbus_return_val_if_fail (connection != NULL, FALSE);
5850 _dbus_return_val_if_fail (path != NULL, FALSE);
5851 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5852 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5853
5854 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
5855
5857 {
5858 _dbus_warn ("%s", error.message);
5859 dbus_error_free (&error);
5860 return FALSE;
5861 }
5862
5863 return retval;
5864}
5865
5877 const char *path)
5878{
5879 char **decomposed_path;
5880
5881 _dbus_return_val_if_fail (connection != NULL, FALSE);
5882 _dbus_return_val_if_fail (path != NULL, FALSE);
5883 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5884
5885 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5886 return FALSE;
5887
5888 CONNECTION_LOCK (connection);
5889
5890 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
5891
5892 dbus_free_string_array (decomposed_path);
5893
5894 return TRUE;
5895}
5896
5909 const char *path,
5910 void **data_p)
5911{
5912 char **decomposed_path;
5913
5914 _dbus_return_val_if_fail (connection != NULL, FALSE);
5915 _dbus_return_val_if_fail (path != NULL, FALSE);
5916 _dbus_return_val_if_fail (data_p != NULL, FALSE);
5917
5918 *data_p = NULL;
5919
5920 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5921 return FALSE;
5922
5923 CONNECTION_LOCK (connection);
5924
5925 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
5926
5927 CONNECTION_UNLOCK (connection);
5928
5929 dbus_free_string_array (decomposed_path);
5930
5931 return TRUE;
5932}
5933
5946 const char *parent_path,
5947 char ***child_entries)
5948{
5949 char **decomposed_path;
5950 dbus_bool_t retval;
5951 _dbus_return_val_if_fail (connection != NULL, FALSE);
5952 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
5953 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
5954 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
5955
5956 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
5957 return FALSE;
5958
5959 CONNECTION_LOCK (connection);
5960
5962 (const char **) decomposed_path,
5963 child_entries);
5964 dbus_free_string_array (decomposed_path);
5965
5966 return retval;
5967}
5968
5969static DBusDataSlotAllocator slot_allocator =
5970 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
5971
5988{
5989 return _dbus_data_slot_allocator_alloc (&slot_allocator,
5990 slot_p);
5991}
5992
6004void
6006{
6007 _dbus_return_if_fail (*slot_p >= 0);
6008
6009 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
6010}
6011
6036 dbus_int32_t slot,
6037 void *data,
6038 DBusFreeFunction free_data_func)
6039{
6040 DBusFreeFunction old_free_func;
6041 void *old_data;
6042 dbus_bool_t retval;
6043
6044 _dbus_return_val_if_fail (connection != NULL, FALSE);
6045 _dbus_return_val_if_fail (slot >= 0, FALSE);
6046
6047 SLOTS_LOCK (connection);
6048
6049 retval = _dbus_data_slot_list_set (&slot_allocator,
6050 &connection->slot_list,
6051 slot, data, free_data_func,
6052 &old_free_func, &old_data);
6053
6054 SLOTS_UNLOCK (connection);
6055
6056 if (retval)
6057 {
6058 /* Do the actual free outside the connection lock */
6059 if (old_free_func)
6060 (* old_free_func) (old_data);
6061 }
6062
6063 return retval;
6064}
6065
6083void*
6085 dbus_int32_t slot)
6086{
6087 void *res;
6088
6089 _dbus_return_val_if_fail (connection != NULL, NULL);
6090 _dbus_return_val_if_fail (slot >= 0, NULL);
6091
6092 SLOTS_LOCK (connection);
6093
6094 res = _dbus_data_slot_list_get (&slot_allocator,
6095 &connection->slot_list,
6096 slot);
6097
6098 SLOTS_UNLOCK (connection);
6099
6100 return res;
6101}
6102
6109void
6111{
6112 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
6113}
6114
6123void
6125 long size)
6126{
6127 _dbus_return_if_fail (connection != NULL);
6128
6129 CONNECTION_LOCK (connection);
6131 size);
6132 CONNECTION_UNLOCK (connection);
6133}
6134
6141long
6143{
6144 long res;
6145
6146 _dbus_return_val_if_fail (connection != NULL, 0);
6147
6148 CONNECTION_LOCK (connection);
6150 CONNECTION_UNLOCK (connection);
6151 return res;
6152}
6153
6162void
6164 long n)
6165{
6166 _dbus_return_if_fail (connection != NULL);
6167
6168 CONNECTION_LOCK (connection);
6170 n);
6171 CONNECTION_UNLOCK (connection);
6172}
6173
6180long
6182{
6183 long res;
6184
6185 _dbus_return_val_if_fail (connection != NULL, 0);
6186
6187 CONNECTION_LOCK (connection);
6189 CONNECTION_UNLOCK (connection);
6190 return res;
6191}
6192
6218void
6220 long size)
6221{
6222 _dbus_return_if_fail (connection != NULL);
6223
6224 CONNECTION_LOCK (connection);
6226 size);
6227 CONNECTION_UNLOCK (connection);
6228}
6229
6236long
6238{
6239 long res;
6240
6241 _dbus_return_val_if_fail (connection != NULL, 0);
6242
6243 CONNECTION_LOCK (connection);
6245 CONNECTION_UNLOCK (connection);
6246 return res;
6247}
6248
6260void
6262 long n)
6263{
6264 _dbus_return_if_fail (connection != NULL);
6265
6266 CONNECTION_LOCK (connection);
6268 n);
6269 CONNECTION_UNLOCK (connection);
6270}
6271
6278long
6280{
6281 long res;
6282
6283 _dbus_return_val_if_fail (connection != NULL, 0);
6284
6285 CONNECTION_LOCK (connection);
6287 CONNECTION_UNLOCK (connection);
6288 return res;
6289}
6290
6301long
6303{
6304 long res;
6305
6306 _dbus_return_val_if_fail (connection != NULL, 0);
6307
6308 CONNECTION_LOCK (connection);
6310 CONNECTION_UNLOCK (connection);
6311 return res;
6312}
6313
6314#ifdef DBUS_ENABLE_STATS
6315void
6316_dbus_connection_get_stats (DBusConnection *connection,
6317 dbus_uint32_t *in_messages,
6318 dbus_uint32_t *in_bytes,
6319 dbus_uint32_t *in_fds,
6320 dbus_uint32_t *in_peak_bytes,
6321 dbus_uint32_t *in_peak_fds,
6322 dbus_uint32_t *out_messages,
6323 dbus_uint32_t *out_bytes,
6324 dbus_uint32_t *out_fds,
6325 dbus_uint32_t *out_peak_bytes,
6326 dbus_uint32_t *out_peak_fds)
6327{
6328 CONNECTION_LOCK (connection);
6329
6330 if (in_messages != NULL)
6331 *in_messages = connection->n_incoming;
6332
6333 _dbus_transport_get_stats (connection->transport,
6334 in_bytes, in_fds, in_peak_bytes, in_peak_fds);
6335
6336 if (out_messages != NULL)
6337 *out_messages = connection->n_outgoing;
6338
6339 if (out_bytes != NULL)
6340 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
6341
6342 if (out_fds != NULL)
6343 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
6344
6345 if (out_peak_bytes != NULL)
6346 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
6347
6348 if (out_peak_fds != NULL)
6349 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
6350
6351 CONNECTION_UNLOCK (connection);
6352}
6353#endif /* DBUS_ENABLE_STATS */
6354
6362long
6364{
6365 long res;
6366
6367 _dbus_return_val_if_fail (connection != NULL, 0);
6368
6369 CONNECTION_LOCK (connection);
6371 CONNECTION_UNLOCK (connection);
6372 return res;
6373}
6374
6375#ifdef DBUS_ENABLE_EMBEDDED_TESTS
6382const char*
6383_dbus_connection_get_address (DBusConnection *connection)
6384{
6385 return _dbus_transport_get_address (connection->transport);
6386}
6387#endif
6388
void dbus_address_entries_free(DBusAddressEntry **entries)
Frees a NULL-terminated array of address entries.
Definition: dbus-address.c:189
dbus_bool_t dbus_parse_address(const char *address, DBusAddressEntry ***entry_result, int *array_len, DBusError *error)
Parses an address string of the form:
Definition: dbus-address.c:363
const char * dbus_address_entry_get_value(DBusAddressEntry *entry, const char *key)
Returns a value from a key of an entry.
Definition: dbus-address.c:244
void _dbus_bus_notify_shared_connection_disconnected_unlocked(DBusConnection *connection)
Internal function that checks to see if this is a shared connection owned by the bus and if it is unr...
Definition: dbus-bus.c:387
dbus_bool_t _dbus_connection_handle_watch(DBusWatch *watch, unsigned int condition, void *data)
A callback for use with dbus_watch_new() to create a DBusWatch.
void _dbus_connection_toggle_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout, dbus_bool_t enabled)
Toggles a timeout and notifies app via connection's DBusTimeoutToggledFunction if available.
dbus_bool_t dbus_connection_has_messages_to_send(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
void _dbus_connection_do_iteration_unlocked(DBusConnection *connection, DBusPendingCall *pending, unsigned int flags, int timeout_milliseconds)
Queues incoming messages and sends outgoing messages for this connection, optionally blocking in the ...
dbus_bool_t _dbus_connection_send_and_unlock(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *client_serial)
Like dbus_connection_send(), but assumes the connection is already locked on function entry,...
DBusConnection * _dbus_connection_new_for_transport(DBusTransport *transport)
Creates a new connection for the given transport.
dbus_bool_t _dbus_connection_has_messages_to_send_unlocked(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
void(* DBusWatchRemoveFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
void _dbus_connection_unlock(DBusConnection *connection)
Releases the connection lock.
void _dbus_connection_lock(DBusConnection *connection)
Acquires the connection lock.
void _dbus_connection_remove_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Removes a watch using the connection's DBusRemoveWatchFunction if available.
dbus_bool_t _dbus_connection_add_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Adds a timeout using the connection's DBusAddTimeoutFunction if available.
void _dbus_connection_toggle_watch_unlocked(DBusConnection *connection, DBusWatch *watch, dbus_bool_t enabled)
Toggles a watch and notifies app via connection's DBusWatchToggledFunction if available.
void(* DBusTimeoutToggleFunction)(DBusTimeoutList *list, DBusTimeout *timeout, dbus_bool_t enabled)
Function to be called in protected_change_timeout() with refcount held.
void(* DBusTimeoutRemoveFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
dbus_bool_t _dbus_connection_add_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Adds a watch using the connection's DBusAddWatchFunction if available.
void _dbus_connection_remove_pending_call(DBusConnection *connection, DBusPendingCall *pending)
Removes a pending call from the connection, such that the pending reply will be ignored.
void _dbus_connection_close_if_only_one_ref(DBusConnection *connection)
Used internally to handle the semantics of dbus_server_set_new_connection_function().
void _dbus_connection_unref_unlocked(DBusConnection *connection)
Decrements the reference count of a DBusConnection.
DBusMessage * _dbus_connection_get_message_to_send(DBusConnection *connection)
Gets the next outgoing message.
dbus_bool_t(* DBusTimeoutAddFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
void _dbus_connection_message_sent_unlocked(DBusConnection *connection, DBusMessage *message)
Notifies the connection that a message has been sent, so the message can be removed from the outgoing...
void _dbus_connection_remove_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Removes a timeout using the connection's DBusRemoveTimeoutFunction if available.
dbus_uint32_t _dbus_connection_get_next_client_serial(DBusConnection *connection)
Allocate and return the next non-zero serial number for outgoing messages.
void(* DBusWatchToggleFunction)(DBusWatchList *list, DBusWatch *watch, dbus_bool_t enabled)
Function to be called in protected_change_watch() with refcount held.
void _dbus_connection_queue_received_message_link(DBusConnection *connection, DBusList *link)
Adds a message-containing list link to the incoming message queue, taking ownership of the link and t...
int _dbus_connection_get_pending_fds_count(DBusConnection *connection)
Return how many file descriptors are pending in the loader.
void _dbus_connection_set_pending_fds_function(DBusConnection *connection, DBusPendingFdsChangeFunction callback, void *data)
Register a function to be called whenever the number of pending file descriptors in the loader change...
dbus_bool_t(* DBusWatchAddFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
void _dbus_connection_block_pending_call(DBusPendingCall *pending)
Blocks until a pending call times out or gets a reply.
void _dbus_connection_queue_synthesized_message_link(DBusConnection *connection, DBusList *link)
Adds a link + message to the incoming message queue.
void _dbus_connection_close_possibly_shared(DBusConnection *connection)
Closes a shared OR private connection, while dbus_connection_close() can only be used on private conn...
DBusConnection * _dbus_connection_ref_unlocked(DBusConnection *connection)
Increments the reference count of a DBusConnection.
void dbus_connection_return_message(DBusConnection *connection, DBusMessage *message)
Used to return a message after peeking at it using dbus_connection_borrow_message().
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
dbus_bool_t dbus_connection_get_object_path_data(DBusConnection *connection, const char *path, void **data_p)
Gets the user data passed to dbus_connection_register_object_path() or dbus_connection_register_fallb...
void dbus_connection_set_max_message_size(DBusConnection *connection, long size)
Specifies the maximum size message this connection is allowed to receive.
void dbus_connection_flush(DBusConnection *connection)
Blocks until the outgoing message queue is empty.
long dbus_connection_get_max_message_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_unix_fds().
void dbus_connection_set_exit_on_disconnect(DBusConnection *connection, dbus_bool_t exit_on_disconnect)
Set whether _exit() should be called when the connection receives a disconnect signal.
dbus_bool_t dbus_connection_get_socket(DBusConnection *connection, int *fd)
Gets the underlying Windows or UNIX socket file descriptor of the connection, if any.
DBusMessage * dbus_connection_pop_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, removing it from the queue.
long dbus_connection_get_max_received_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_unix_fds().
dbus_bool_t dbus_connection_register_object_path(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data)
Registers a handler for a given path in the object hierarchy.
void dbus_connection_close(DBusConnection *connection)
Closes a private connection, so no further data can be sent or received.
void dbus_connection_set_max_message_unix_fds(DBusConnection *connection, long n)
Specifies the maximum number of unix fds a message on this connection is allowed to receive.
void dbus_connection_set_wakeup_main_function(DBusConnection *connection, DBusWakeupMainFunction wakeup_main_function, void *data, DBusFreeFunction free_data_function)
Sets the mainloop wakeup function for the connection.
dbus_bool_t dbus_connection_get_windows_user(DBusConnection *connection, char **windows_sid_p)
Gets the Windows user SID of the connection if known.
dbus_bool_t dbus_connection_get_is_authenticated(DBusConnection *connection)
Gets whether the connection was authenticated.
void dbus_connection_send_preallocated(DBusConnection *connection, DBusPreallocatedSend *preallocated, DBusMessage *message, dbus_uint32_t *client_serial)
Sends a message using preallocated resources.
dbus_bool_t dbus_connection_read_write(DBusConnection *connection, int timeout_milliseconds)
This function is intended for use with applications that don't want to write a main loop and deal wit...
long dbus_connection_get_max_received_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_size().
dbus_bool_t dbus_connection_get_unix_fd(DBusConnection *connection, int *fd)
Get the UNIX file descriptor of the connection, if any.
void(* DBusDispatchStatusFunction)(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
Called when the return value of dbus_connection_get_dispatch_status() may have changed.
dbus_bool_t dbus_connection_can_send_type(DBusConnection *connection, int type)
Tests whether a certain type can be send via the connection.
dbus_bool_t dbus_connection_list_registered(DBusConnection *connection, const char *parent_path, char ***child_entries)
Lists the registered fallback handlers and object path handlers at the given parent_path.
void * dbus_connection_get_data(DBusConnection *connection, dbus_int32_t slot)
Retrieves data previously set with dbus_connection_set_data().
DBusConnection * dbus_connection_open_private(const char *address, DBusError *error)
Opens a new, dedicated connection to a remote address.
long dbus_connection_get_outgoing_size(DBusConnection *connection)
Gets the approximate size in bytes of all messages in the outgoing message queue.
void dbus_connection_set_dispatch_status_function(DBusConnection *connection, DBusDispatchStatusFunction function, void *data, DBusFreeFunction free_data_function)
Set a function to be invoked when the dispatch status changes.
dbus_bool_t dbus_connection_read_write_dispatch(DBusConnection *connection, int timeout_milliseconds)
This function is intended for use with applications that don't want to write a main loop and deal wit...
DBusHandlerResult(* DBusHandleMessageFunction)(DBusConnection *connection, DBusMessage *message, void *user_data)
Called when a message needs to be handled.
void dbus_connection_remove_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data)
Removes a previously-added message filter.
dbus_bool_t dbus_connection_get_is_connected(DBusConnection *connection)
Gets whether the connection is currently open.
DBusPreallocatedSend * dbus_connection_preallocate_send(DBusConnection *connection)
Preallocates resources needed to send a message, allowing the message to be sent without the possibil...
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
void dbus_connection_unref(DBusConnection *connection)
Decrements the reference count of a DBusConnection, and finalizes it if the count reaches zero.
void dbus_connection_set_max_received_size(DBusConnection *connection, long size)
Sets the maximum total number of bytes that can be used for all messages received on this connection.
void(* DBusTimeoutToggledFunction)(DBusTimeout *timeout, void *data)
Called when dbus_timeout_get_enabled() may return a different value than it did before.
DBusDispatchStatus dbus_connection_dispatch(DBusConnection *connection)
Processes any incoming data.
dbus_bool_t dbus_connection_unregister_object_path(DBusConnection *connection, const char *path)
Unregisters the handler registered with exactly the given path.
void dbus_connection_set_unix_user_function(DBusConnection *connection, DBusAllowUnixUserFunction function, void *data, DBusFreeFunction free_data_function)
Sets a predicate function used to determine whether a given user ID is allowed to connect.
dbus_bool_t dbus_connection_try_register_object_path(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a handler for a given path in the object hierarchy.
void dbus_connection_steal_borrowed_message(DBusConnection *connection, DBusMessage *message)
Used to keep a message after peeking at it using dbus_connection_borrow_message().
dbus_bool_t dbus_connection_allocate_data_slot(dbus_int32_t *slot_p)
Allocates an integer ID to be used for storing application-specific data on any DBusConnection.
void dbus_connection_set_change_sigpipe(dbus_bool_t will_modify_sigpipe)
This function sets a global flag for whether dbus_connection_new() will set SIGPIPE behavior to SIG_I...
long dbus_connection_get_max_message_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_size().
void dbus_connection_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for connection data slots.
dbus_bool_t(* DBusAddTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus needs a new timeout to be monitored by the main loop.
void dbus_connection_set_max_received_unix_fds(DBusConnection *connection, long n)
Sets the maximum total number of unix fds that can be used for all messages received on this connecti...
dbus_bool_t dbus_connection_set_data(DBusConnection *connection, dbus_int32_t slot, void *data, DBusFreeFunction free_data_func)
Stores a pointer on a DBusConnection, along with an optional function to be used for freeing the data...
DBusDispatchStatus dbus_connection_get_dispatch_status(DBusConnection *connection)
Gets the current state of the incoming message queue.
DBusMessage * dbus_connection_send_with_reply_and_block(DBusConnection *connection, DBusMessage *message, int timeout_milliseconds, DBusError *error)
Sends a message and blocks a certain time period while waiting for a reply.
dbus_bool_t dbus_connection_try_register_fallback(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a fallback handler for a given subsection of the object hierarchy.
dbus_bool_t dbus_connection_get_adt_audit_session_data(DBusConnection *connection, void **data, dbus_int32_t *data_size)
Gets the ADT audit data of the connection if any.
DBusMessage * dbus_connection_borrow_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, leaving it in the queue.
dbus_bool_t dbus_connection_send_with_reply(DBusConnection *connection, DBusMessage *message, DBusPendingCall **pending_return, int timeout_milliseconds)
Queues a message to send, as with dbus_connection_send(), but also returns a DBusPendingCall used to ...
void dbus_connection_set_windows_user_function(DBusConnection *connection, DBusAllowWindowsUserFunction function, void *data, DBusFreeFunction free_data_function)
Sets a predicate function used to determine whether a given user ID is allowed to connect.
dbus_bool_t dbus_connection_get_is_anonymous(DBusConnection *connection)
Gets whether the connection is not authenticated as a specific user.
dbus_bool_t dbus_connection_set_timeout_functions(DBusConnection *connection, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the timeout functions for the connection.
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
dbus_bool_t(* DBusAllowUnixUserFunction)(DBusConnection *connection, unsigned long uid, void *data)
Called during authentication to check whether the given UNIX user ID is allowed to connect,...
DBusDispatchStatus
Indicates the status of incoming data on a DBusConnection.
dbus_bool_t dbus_connection_register_fallback(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data)
Registers a fallback handler for a given subsection of the object hierarchy.
DBusConnection * dbus_connection_open(const char *address, DBusError *error)
Gets a connection to a remote address.
void dbus_connection_free_preallocated_send(DBusConnection *connection, DBusPreallocatedSend *preallocated)
Frees preallocated message-sending resources from dbus_connection_preallocate_send().
long dbus_connection_get_outgoing_unix_fds(DBusConnection *connection)
Gets the approximate number of uni fds of all messages in the outgoing message queue.
void(* DBusWakeupMainFunction)(void *data)
Called when the main loop's thread should be notified that there's now work to do.
void dbus_connection_set_allow_anonymous(DBusConnection *connection, dbus_bool_t value)
This function must be called on the server side of a connection when the connection is first seen in ...
dbus_bool_t dbus_connection_add_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data, DBusFreeFunction free_data_function)
Adds a message filter.
dbus_bool_t dbus_connection_send(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial)
Adds a message to the outgoing message queue.
DBusConnection * dbus_connection_ref(DBusConnection *connection)
Increments the reference count of a DBusConnection.
char * dbus_connection_get_server_id(DBusConnection *connection)
Gets the ID of the server address we are authenticated to, if this connection is on the client side.
dbus_bool_t(* DBusAllowWindowsUserFunction)(DBusConnection *connection, const char *user_sid, void *data)
Called during authentication to check whether the given Windows user ID is allowed to connect,...
dbus_bool_t dbus_connection_set_watch_functions(DBusConnection *connection, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions for the connection.
void(* DBusRemoveTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus no longer needs a timeout to be monitored by the main loop.
dbus_bool_t dbus_connection_get_unix_process_id(DBusConnection *connection, unsigned long *pid)
Gets the process ID of the connection if any.
dbus_bool_t dbus_connection_get_unix_user(DBusConnection *connection, unsigned long *uid)
Gets the UNIX user ID of the connection if known.
void dbus_connection_set_route_peer_messages(DBusConnection *connection, dbus_bool_t value)
Normally DBusConnection automatically handles all messages to the org.freedesktop....
@ DBUS_DISPATCH_NEED_MEMORY
More memory is needed to continue.
@ DBUS_DISPATCH_COMPLETE
All currently available data has been processed.
@ DBUS_DISPATCH_DATA_REMAINS
There is more data to potentially convert to messages.
void _dbus_data_slot_allocator_free(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Deallocates an ID previously allocated with _dbus_data_slot_allocator_alloc().
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
void _dbus_data_slot_list_free(DBusDataSlotList *list)
Frees the data slot list and all data slots contained in it, calling application-provided free functi...
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
dbus_bool_t _dbus_data_slot_list_set(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot, void *data, DBusFreeFunction free_data_func, DBusFreeFunction *old_free_func, void **old_data)
Stores a pointer in the data slot list, along with an optional function to be used for freeing the da...
dbus_bool_t _dbus_data_slot_allocator_alloc(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Allocates an integer ID to be used for storing data in a DBusDataSlotList.
Definition: dbus-dataslot.c:69
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition: dbus-errors.c:279
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition: dbus-errors.c:302
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
int _dbus_hash_table_get_n_entries(DBusHashTable *table)
Gets the number of hash entries in a hash table.
Definition: dbus-hash.c:1407
void * _dbus_hash_iter_get_value(DBusHashIter *iter)
Gets the value of the current entry.
Definition: dbus-hash.c:613
dbus_bool_t _dbus_hash_table_insert_int(DBusHashTable *table, int key, void *value)
Creates a hash entry with the given key and value.
Definition: dbus-hash.c:1258
dbus_bool_t _dbus_hash_table_insert_string(DBusHashTable *table, char *key, void *value)
Creates a hash entry with the given key and value.
Definition: dbus-hash.c:1224
void _dbus_hash_table_unref(DBusHashTable *table)
Decrements the reference count for a hash table, freeing the hash table if the count reaches zero.
Definition: dbus-hash.c:361
dbus_bool_t _dbus_hash_iter_next(DBusHashIter *iter)
Move the hash iterator forward one step, to the next hash entry.
Definition: dbus-hash.c:543
void _dbus_hash_iter_init(DBusHashTable *table, DBusHashIter *iter)
Initializes a hash table iterator.
Definition: dbus-hash.c:517
DBusHashTable * _dbus_hash_table_new(DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function)
Constructs a new hash table.
Definition: dbus-hash.c:285
dbus_bool_t _dbus_hash_table_remove_int(DBusHashTable *table, int key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1161
dbus_bool_t _dbus_hash_table_remove_string(DBusHashTable *table, const char *key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1133
void * _dbus_hash_table_lookup_string(DBusHashTable *table, const char *key)
Looks up the value for a given string in a hash table of type DBUS_HASH_STRING.
Definition: dbus-hash.c:1059
void _dbus_hash_iter_remove_entry(DBusHashIter *iter)
Removes the current entry from the hash table.
Definition: dbus-hash.c:592
void * _dbus_hash_table_lookup_int(DBusHashTable *table, int key)
Looks up the value for a given integer in a hash table of type DBUS_HASH_INT.
Definition: dbus-hash.c:1084
@ DBUS_HASH_INT
Hash keys are integers.
Definition: dbus-hash.h:70
@ DBUS_HASH_STRING
Hash keys are strings.
Definition: dbus-hash.h:69
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
void _dbus_warn_check_failed(const char *format,...)
Prints a "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
void(* DBusForeachFunction)(void *element, void *data)
Used to iterate over each item in a collection, such as a DBusList.
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:567
dbus_bool_t _dbus_list_copy(DBusList **list, DBusList **dest)
Copies a list.
Definition: dbus-list.c:697
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:628
void * _dbus_list_get_last(DBusList **list)
Gets the last data in the list.
Definition: dbus-list.c:596
dbus_bool_t _dbus_list_remove(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:415
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:315
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:527
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition: dbus-list.c:612
DBusList * _dbus_list_get_last_link(DBusList **list)
Gets the last link in the list.
Definition: dbus-list.c:580
void _dbus_list_unlink(DBusList **list, DBusList *link)
Removes the given link from the list, but doesn't free it.
Definition: dbus-list.c:499
#define _dbus_list_get_prev_link(list, link)
Gets the previous link in the list, or NULL if there are no more links.
Definition: dbus-list.h:117
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:254
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:649
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:759
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:542
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:333
dbus_bool_t _dbus_list_prepend(DBusList **list, void *data)
Prepends a value to the list.
Definition: dbus-list.c:292
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:242
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:270
#define _dbus_list_get_next_link(list, link)
Gets the next link in the list, or NULL if there are no more links.
Definition: dbus-list.h:116
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition: dbus-memory.c:782
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_register_shutdown_func(DBusShutdownFunction function, void *data)
Register a cleanup function to be called exactly once the next time dbus_shutdown() is called.
Definition: dbus-memory.c:811
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:63
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:750
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:277
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:407
const char * dbus_message_type_to_string(int type)
Utility function to convert a D-Bus message type into a machine-readable string (not translated).
void _dbus_message_remove_counter(DBusMessage *message, DBusCounter *counter)
Removes a counter tracking the size/unix fds of this message, and decrements the counter by the size/...
Definition: dbus-message.c:375
void _dbus_message_add_counter_link(DBusMessage *message, DBusList *link)
Adds a counter to be incremented immediately with the size/unix fds of this message,...
Definition: dbus-message.c:303
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *iface)
Checks if the message has an interface.
void dbus_message_set_no_reply(DBusMessage *message, dbus_bool_t no_reply)
Sets a flag indicating that the message does not want a reply; if this flag is set,...
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
const char * dbus_message_get_path(DBusMessage *message)
Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitt...
const char * dbus_message_get_interface(DBusMessage *message)
Gets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted...
DBusMessage * dbus_message_new_error(DBusMessage *reply_to, const char *error_name, const char *error_message)
Creates a new message that is an error reply to another message.
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
DBusMessage * dbus_message_new_signal(const char *path, const char *iface, const char *name)
Constructs a new message representing a signal emission.
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0.
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
dbus_bool_t dbus_message_is_method_call(DBusMessage *message, const char *iface, const char *method)
Checks whether the message is a method call with the given interface and member fields.
dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message, dbus_uint32_t reply_serial)
Sets the reply serial of a message (the serial of the message this is a reply to).
dbus_bool_t dbus_message_is_signal(DBusMessage *message, const char *iface, const char *signal_name)
Checks whether the message is a signal with the given interface and member fields.
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
void _dbus_object_tree_free_all_unlocked(DBusObjectTree *tree)
Free all the handlers in the tree.
void _dbus_object_tree_unregister_and_unlock(DBusObjectTree *tree, const char **path)
Unregisters an object subtree that was registered with the same path.
void _dbus_object_tree_unref(DBusObjectTree *tree)
Decrement the reference count.
dbus_bool_t _dbus_object_tree_list_registered_and_unlock(DBusObjectTree *tree, const char **parent_path, char ***child_entries)
Lists the registered fallback handlers and object path handlers at the given parent_path.
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
dbus_bool_t _dbus_object_tree_register(DBusObjectTree *tree, dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a new subtree in the global object tree.
void * _dbus_object_tree_get_user_data_unlocked(DBusObjectTree *tree, const char **path)
Looks up the data passed to _dbus_object_tree_register() for a handler at the given path.
DBusHandlerResult _dbus_object_tree_dispatch_and_unlock(DBusObjectTree *tree, DBusMessage *message, dbus_bool_t *found_object)
Tries to dispatch a message by directing it to handler for the object path listed in the message head...
DBusObjectTree * _dbus_object_tree_new(DBusConnection *connection)
Creates a new object tree, representing a mapping from paths to handler vtables.
void _dbus_pending_call_finish_completion(DBusPendingCall *pending)
Call the notifier function for the pending call.
DBusConnection * _dbus_pending_call_get_connection_and_lock(DBusPendingCall *pending)
Gets the connection associated with this pending call.
DBUS_PRIVATE_EXPORT DBusPendingCall * _dbus_pending_call_ref_unlocked(DBusPendingCall *pending)
Increments the reference count on a pending call, while the lock on its connection is already held.
void _dbus_pending_call_queue_timeout_error_unlocked(DBusPendingCall *pending, DBusConnection *connection)
If the pending call hasn't been timed out, add its timeout error reply to the connection's incoming m...
DBUS_PRIVATE_EXPORT void _dbus_pending_call_unref_and_unlock(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0.
dbus_bool_t _dbus_pending_call_get_completed_unlocked(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
void _dbus_pending_call_set_reply_unlocked(DBusPendingCall *pending, DBusMessage *message)
Sets the reply of a pending call with the given message, or if the message is NULL,...
DBUS_PRIVATE_EXPORT DBusPendingCall * _dbus_pending_call_new_unlocked(DBusConnection *connection, int timeout_milliseconds, DBusTimeoutHandler timeout_handler)
Creates a new pending reply object.
dbus_bool_t _dbus_pending_call_set_timeout_error_unlocked(DBusPendingCall *pending, DBusMessage *message, dbus_uint32_t serial)
Sets the reply message associated with the pending call to a timeout error.
#define CONNECTION_LOCK(connection)
Internals of DBusPendingCall.
#define CONNECTION_UNLOCK(connection)
shorter and more visible way to write _dbus_connection_unlock()
void _dbus_pending_call_start_completion_unlocked(DBusPendingCall *pending)
Sets the pending call to completed.
dbus_bool_t _dbus_pending_call_is_timeout_added_unlocked(DBusPendingCall *pending)
Checks to see if a timeout has been added.
dbus_uint32_t _dbus_pending_call_get_reply_serial_unlocked(DBusPendingCall *pending)
Gets the reply's serial number.
DBusConnection * _dbus_pending_call_get_connection_unlocked(DBusPendingCall *pending)
Gets the connection associated with this pending call.
DBusTimeout * _dbus_pending_call_get_timeout_unlocked(DBusPendingCall *pending)
Retrives the timeout.
void _dbus_pending_call_set_timeout_added_unlocked(DBusPendingCall *pending, dbus_bool_t is_added)
Sets wether the timeout has been added.
DBusPendingCall * dbus_pending_call_ref(DBusPendingCall *pending)
Increments the reference count on a pending call.
DBusMessage * dbus_pending_call_steal_reply(DBusPendingCall *pending)
Gets the reply, or returns NULL if none has been received yet.
void dbus_pending_call_block(DBusPendingCall *pending)
Block until the pending call is completed.
dbus_bool_t dbus_pending_call_get_completed(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
void dbus_pending_call_unref(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_ERROR_UNKNOWN_METHOD
Method name you invoked isn't known by the object you invoked it on.
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_ERROR_OBJECT_PATH_IN_USE
There's already an object with the requested object path.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_ERROR_UNKNOWN_OBJECT
Object you invoked a method on isn't known.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_DISCONNECTED
The connection is disconnected and you're trying to use it.
DBusCounter * _dbus_counter_new(void)
Creates a new DBusCounter.
long _dbus_counter_get_unix_fd_value(DBusCounter *counter)
Gets the current value of the unix fd counter.
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
long _dbus_counter_get_size_value(DBusCounter *counter)
Gets the current value of the size counter.
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
DBusHandlerResult
Results that a message handler can return.
Definition: dbus-shared.h:67
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:82
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
Definition: dbus-shared.h:105
#define DBUS_INTERFACE_PEER
The interface supported by most dbus peers.
Definition: dbus-shared.h:99
@ DBUS_HANDLER_RESULT_NEED_MEMORY
Need more memory in order to return DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLE...
Definition: dbus-shared.h:70
@ DBUS_HANDLER_RESULT_HANDLED
Message has had its effect - no need to run more handlers.
Definition: dbus-shared.h:68
@ DBUS_HANDLER_RESULT_NOT_YET_HANDLED
Message has not had any effect - see if other handlers want it.
Definition: dbus-shared.h:69
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1114
void _dbus_exit(int code)
Exit the process, returning the given value.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
void _dbus_rmutex_new_at_location(DBusRMutex **location_p)
Creates a new mutex or creates a no-op mutex if threads are not initialized.
Definition: dbus-threads.c:53
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:107
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a condition variable; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:224
DBUS_PRIVATE_EXPORT void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:150
void _dbus_condvar_wait(DBusCondVar *cond, DBusCMutex *mutex)
Atomically unlocks the mutex and waits for the conditions variable to be signalled.
Definition: dbus-threads.c:240
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition: dbus-threads.c:199
void _dbus_cmutex_new_at_location(DBusCMutex **location_p)
Creates a new mutex or creates a no-op mutex if threads are not initialized.
Definition: dbus-threads.c:77
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition: dbus-threads.c:278
dbus_bool_t _dbus_condvar_wait_timeout(DBusCondVar *cond, DBusCMutex *mutex, int timeout_milliseconds)
Atomically unlocks the mutex and waits for the conditions variable to be signalled,...
Definition: dbus-threads.c:261
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:136
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:164
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:94
struct DBusMutex DBusMutex
An opaque mutex type provided by the DBusThreadFunctions implementation installed by dbus_threads_ini...
Definition: dbus-threads.h:41
dbus_bool_t _dbus_timeout_list_add_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Adds a new timeout to the timeout list, invoking the application DBusAddTimeoutFunction if appropriat...
Definition: dbus-timeout.c:314
void _dbus_timeout_list_free(DBusTimeoutList *timeout_list)
Frees a DBusTimeoutList.
Definition: dbus-timeout.c:215
void _dbus_timeout_list_toggle_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout, dbus_bool_t enabled)
Sets a timeout to the given enabled state, invoking the application's DBusTimeoutToggledFunction if a...
Definition: dbus-timeout.c:366
DBusTimeoutList * _dbus_timeout_list_new(void)
Creates a new timeout list.
Definition: dbus-timeout.c:198
dbus_bool_t _dbus_timeout_list_set_functions(DBusTimeoutList *timeout_list, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the timeout functions.
Definition: dbus-timeout.c:243
void _dbus_timeout_list_remove_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Removes a timeout from the timeout list, invoking the application's DBusRemoveTimeoutFunction if appr...
Definition: dbus-timeout.c:344
DBUS_EXPORT int dbus_timeout_get_interval(DBusTimeout *timeout)
Gets the timeout interval.
Definition: dbus-timeout.c:444
void _dbus_transport_set_max_message_size(DBusTransport *transport, long size)
See dbus_connection_set_max_message_size().
void _dbus_transport_set_max_received_size(DBusTransport *transport, long size)
See dbus_connection_set_max_received_size().
DBusDispatchStatus _dbus_transport_get_dispatch_status(DBusTransport *transport)
Reports our current dispatch status (whether there's buffered data to be queued as messages,...
int _dbus_transport_get_pending_fds_count(DBusTransport *transport)
Return how many file descriptors are pending in the loader.
dbus_bool_t _dbus_transport_get_adt_audit_session_data(DBusTransport *transport, void **data, int *data_size)
See dbus_connection_get_adt_audit_session_data().
dbus_bool_t _dbus_transport_get_windows_user(DBusTransport *transport, char **windows_sid_p)
See dbus_connection_get_windows_user().
dbus_bool_t _dbus_transport_queue_messages(DBusTransport *transport)
Processes data we've read while handling a watch, potentially converting some of it to messages and q...
dbus_bool_t _dbus_transport_get_socket_fd(DBusTransport *transport, DBusSocket *fd_p)
Get the socket file descriptor, if any.
const char * _dbus_transport_get_address(DBusTransport *transport)
Gets the address of a transport.
dbus_bool_t _dbus_transport_handle_watch(DBusTransport *transport, DBusWatch *watch, unsigned int condition)
Handles a watch by reading data, writing data, or disconnecting the transport, as appropriate for the...
DBusTransport * _dbus_transport_ref(DBusTransport *transport)
Increments the reference count for the transport.
dbus_bool_t _dbus_transport_peek_is_authenticated(DBusTransport *transport)
Returns TRUE if we have been authenticated.
void _dbus_transport_set_allow_anonymous(DBusTransport *transport, dbus_bool_t value)
See dbus_connection_set_allow_anonymous()
void _dbus_transport_disconnect(DBusTransport *transport)
Closes our end of the connection to a remote application.
long _dbus_transport_get_max_received_size(DBusTransport *transport)
See dbus_connection_get_max_received_size().
dbus_bool_t _dbus_transport_set_connection(DBusTransport *transport, DBusConnection *connection)
Sets the connection using this transport.
void _dbus_transport_set_unix_user_function(DBusTransport *transport, DBusAllowUnixUserFunction function, void *data, DBusFreeFunction free_data_function, void **old_data, DBusFreeFunction *old_free_data_function)
See dbus_connection_set_unix_user_function().
long _dbus_transport_get_max_message_unix_fds(DBusTransport *transport)
See dbus_connection_get_max_message_unix_fds().
void _dbus_transport_set_max_received_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_received_unix_fds().
void _dbus_transport_unref(DBusTransport *transport)
Decrements the reference count for the transport.
dbus_bool_t _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
Returns TRUE if the transport supports sending unix fds.
dbus_bool_t _dbus_transport_try_to_authenticate(DBusTransport *transport)
Returns TRUE if we have been authenticated.
void _dbus_transport_do_iteration(DBusTransport *transport, unsigned int flags, int timeout_milliseconds)
Performs a single poll()/select() on the transport's file descriptors and then reads/writes data as a...
long _dbus_transport_get_max_received_unix_fds(DBusTransport *transport)
See dbus_connection_set_max_received_unix_fds().
dbus_bool_t _dbus_transport_get_is_connected(DBusTransport *transport)
Returns TRUE if the transport has not been disconnected.
void _dbus_transport_set_max_message_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_message_unix_fds().
void _dbus_transport_set_pending_fds_function(DBusTransport *transport, void(*callback)(void *), void *data)
Register a function to be called whenever the number of pending file descriptors in the loader change...
void _dbus_transport_set_windows_user_function(DBusTransport *transport, DBusAllowWindowsUserFunction function, void *data, DBusFreeFunction free_data_function, void **old_data, DBusFreeFunction *old_free_data_function)
See dbus_connection_set_windows_user_function().
long _dbus_transport_get_max_message_size(DBusTransport *transport)
See dbus_connection_get_max_message_size().
dbus_bool_t _dbus_transport_get_unix_process_id(DBusTransport *transport, unsigned long *pid)
See dbus_connection_get_unix_process_id().
DBusTransport * _dbus_transport_open(DBusAddressEntry *entry, DBusError *error)
Try to open a new transport for the given address entry.
const char * _dbus_transport_get_server_id(DBusTransport *transport)
Gets the id of the server we are connected to (see dbus_server_get_id()).
dbus_bool_t _dbus_transport_get_is_anonymous(DBusTransport *transport)
See dbus_connection_get_is_anonymous().
dbus_bool_t _dbus_transport_get_unix_user(DBusTransport *transport, unsigned long *uid)
See dbus_connection_get_unix_user().
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
int dbus_int32_t
A 32-bit signed integer on all platforms.
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
dbus_bool_t _dbus_watch_list_add_watch(DBusWatchList *watch_list, DBusWatch *watch)
Adds a new watch to the watch list, invoking the application DBusAddWatchFunction if appropriate.
Definition: dbus-watch.c:382
void _dbus_watch_list_toggle_watch(DBusWatchList *watch_list, DBusWatch *watch, dbus_bool_t enabled)
Sets a watch to the given enabled state, invoking the application's DBusWatchToggledFunction if appro...
Definition: dbus-watch.c:442
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
dbus_bool_t _dbus_watch_list_set_functions(DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions.
Definition: dbus-watch.c:296
void _dbus_watch_list_remove_watch(DBusWatchList *watch_list, DBusWatch *watch)
Removes a watch from the watch list, invoking the application's DBusRemoveWatchFunction if appropriat...
Definition: dbus-watch.c:415
Internals of DBusAddressEntry.
Definition: dbus-address.c:44
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:308
Implementation details of DBusConnection.
void * dispatch_status_data
Application data for dispatch_status_function.
int n_outgoing
Length of outgoing queue.
DBusDataSlotList slot_list
Data stored by allocated integer ID.
dbus_bool_t dispatch_acquired
Someone has dispatch path (can drain incoming queue)
DBusCondVar * dispatch_cond
Notify when dispatch_acquired is available.
DBusWakeupMainFunction wakeup_main_function
Function to wake up the mainloop
unsigned int exit_on_disconnect
If TRUE, exit after handling disconnect signal.
DBusList * filter_list
List of filters.
unsigned int have_connection_lock
Used to check locking.
unsigned int disconnected_message_processed
We did our default handling of the disconnected message, such as closing the connection.
dbus_uint32_t client_serial
Client serial.
unsigned int disconnected_message_arrived
We popped or are dispatching the disconnected message.
DBusCounter * outgoing_counter
Counts size of outgoing messages.
DBusCondVar * io_path_cond
Notify when io_path_acquired is available.
DBusAtomic refcount
Reference count.
DBusList * outgoing_messages
Queue of messages we need to send, send the end of the list first.
DBusFreeFunction free_dispatch_status_data
free dispatch_status_data
DBusRMutex * slot_mutex
Lock on slot_list so overall connection lock need not be taken.
DBusFreeFunction free_wakeup_main_data
free wakeup_main_data
DBusTransport * transport
Object that sends/receives messages over network.
DBusRMutex * mutex
Lock on the entire DBusConnection.
int n_incoming
Length of incoming queue.
dbus_bool_t io_path_acquired
Someone has transport io path (can use the transport to read/write messages)
DBusList * disconnect_message_link
Preallocated list node for queueing the disconnection message.
DBusCMutex * io_path_mutex
Protects io_path_acquired.
DBusList * incoming_messages
Queue of messages we have received, end of the list received most recently.
unsigned int shareable
TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more...
unsigned int route_peer_messages
If TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don't handle them automatically.
DBusWatchList * watches
Stores active watches.
void * wakeup_main_data
Application data for wakeup_main_function.
DBusObjectTree * objects
Object path handlers registered with this connection.
char * server_guid
GUID of server if we are in shared_connections, NULL if server GUID is unknown or connection is priva...
DBusHashTable * pending_replies
Hash of message serials to DBusPendingCall.
DBusCMutex * dispatch_mutex
Protects dispatch_acquired.
DBusMessage * message_borrowed
Filled in if the first incoming message has been borrowed; dispatch_acquired will be set by the borro...
DBusTimeoutList * timeouts
Stores active timeouts.
DBusDispatchStatus last_dispatch_status
The last dispatch status we reported to the application.
DBusDispatchStatusFunction dispatch_status_function
Function on dispatch status changes
DBusList * expired_messages
Messages that will be released when we next unlock.
Internals of DBusCounter.
An allocator that tracks a set of slot IDs.
Definition: dbus-dataslot.h:56
Data structure that stores the actual user data set at a given slot.
Definition: dbus-dataslot.h:70
Object representing an exception.
Definition: dbus-errors.h:49
const char * name
public error name field
Definition: dbus-errors.h:50
const char * message
public error message field
Definition: dbus-errors.h:51
Hash iterator object.
Definition: dbus-hash.h:50
Internals of DBusHashTable.
Definition: dbus-hash.c:168
A node in a linked list.
Definition: dbus-list.h:35
void * data
Data stored at this element.
Definition: dbus-list.h:38
Internal struct representing a message filter function.
DBusAtomic refcount
Reference count.
DBusHandleMessageFunction function
Function to call to filter.
void * user_data
User data for the function.
DBusFreeFunction free_user_data_function
Function to free the user data.
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:62
Internals of DBusMessage.
Virtual table that must be implemented to handle a portion of the object path hierarchy.
Internals of DBusObjectTree.
Implementation details of DBusPendingCall - all fields are private.
Internals of DBusPreallocatedSend.
DBusConnection * connection
Connection we'd send the message to.
DBusList * counter_link
Preallocated link in the resource counter.
DBusList * queue_link
Preallocated link in the queue.
Socket interface.
Definition: dbus-sysdeps.h:175
DBusTimeoutList implementation details.
Definition: dbus-timeout.c:181
Internals of DBusTimeout.
Definition: dbus-timeout.c:41
Object representing a transport such as a socket.
DBusWatchList implementation details.
Definition: dbus-watch.c:215
Implementation of DBusWatch.
Definition: dbus-watch.c:41