D-Bus  1.14.10
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 
206 static 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 
223 typedef struct DBusMessageFilter DBusMessageFilter;
224 
229 {
232  void *user_data;
234 };
235 
236 
241 {
245 };
246 
247 #if HAVE_DECL_MSG_NOSIGNAL
248 static DBusAtomic _dbus_modify_sigpipe = { FALSE };
249 #else
250 static DBusAtomic _dbus_modify_sigpipe = { TRUE };
251 #endif
252 
257 {
291  dbus_uint32_t client_serial;
306  char *server_guid;
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 builtin_filters_enabled : 1;
321  unsigned int route_peer_messages : 1;
323  unsigned int disconnected_message_arrived : 1;
331 #ifndef DBUS_DISABLE_CHECKS
332  unsigned int have_connection_lock : 1;
333 #endif
334 
335 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
336  int generation;
337 #endif
338 };
339 
340 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
341 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
342  DBusDispatchStatus new_status);
343 static void _dbus_connection_last_unref (DBusConnection *connection);
344 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
345 static void _dbus_connection_release_dispatch (DBusConnection *connection);
346 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
347 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
348 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
349 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
350  dbus_uint32_t client_serial);
351 
352 static DBusMessageFilter *
353 _dbus_message_filter_ref (DBusMessageFilter *filter)
354 {
355 #ifdef DBUS_DISABLE_ASSERT
356  _dbus_atomic_inc (&filter->refcount);
357 #else
358  dbus_int32_t old_value;
359 
360  old_value = _dbus_atomic_inc (&filter->refcount);
361  _dbus_assert (old_value > 0);
362 #endif
363 
364  return filter;
365 }
366 
367 static void
368 _dbus_message_filter_unref (DBusMessageFilter *filter)
369 {
370  dbus_int32_t old_value;
371 
372  old_value = _dbus_atomic_dec (&filter->refcount);
373  _dbus_assert (old_value > 0);
374 
375  if (old_value == 1)
376  {
377  if (filter->free_user_data_function)
378  (* filter->free_user_data_function) (filter->user_data);
379 
380  dbus_free (filter);
381  }
382 }
383 
389 void
391 {
392  CONNECTION_LOCK (connection);
393 }
394 
400 void
402 {
403  DBusList *expired_messages;
404  DBusList *iter;
405 
406  if (TRACE_LOCKS)
407  {
408  _dbus_verbose ("UNLOCK\n");
409  }
410 
411  /* If we had messages that expired (fell off the incoming or outgoing
412  * queues) while we were locked, actually release them now */
413  expired_messages = connection->expired_messages;
414  connection->expired_messages = NULL;
415 
416  RELEASING_LOCK_CHECK (connection);
417  _dbus_rmutex_unlock (connection->mutex);
418 
419  for (iter = _dbus_list_pop_first_link (&expired_messages);
420  iter != NULL;
421  iter = _dbus_list_pop_first_link (&expired_messages))
422  {
423  DBusMessage *message = iter->data;
424 
425  dbus_message_unref (message);
426  _dbus_list_free_link (iter);
427  }
428 }
429 
437 static void
438 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
439 {
440  if (connection->wakeup_main_function)
441  (*connection->wakeup_main_function) (connection->wakeup_main_data);
442 }
443 
444 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
457 void
458 _dbus_connection_test_get_locks (DBusConnection *connection,
459  DBusMutex **mutex_loc,
460  DBusMutex **dispatch_mutex_loc,
461  DBusMutex **io_path_mutex_loc,
462  DBusCondVar **dispatch_cond_loc,
463  DBusCondVar **io_path_cond_loc)
464 {
465  *mutex_loc = (DBusMutex *) connection->mutex;
466  *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
467  *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
468  *dispatch_cond_loc = connection->dispatch_cond;
469  *io_path_cond_loc = connection->io_path_cond;
470 }
471 #endif
472 
481 void
483  DBusList *link)
484 {
485  DBusPendingCall *pending;
486  dbus_uint32_t reply_serial;
487  DBusMessage *message;
488 
490 
492  link);
493  message = link->data;
494 
495  /* If this is a reply we're waiting on, remove timeout for it */
496  reply_serial = dbus_message_get_reply_serial (message);
497  if (reply_serial != 0)
498  {
499  pending = _dbus_hash_table_lookup_int (connection->pending_replies,
500  reply_serial);
501  if (pending != NULL)
502  {
506 
508  }
509  }
510 
511 
512 
513  connection->n_incoming += 1;
514 
515  _dbus_connection_wakeup_mainloop (connection);
516 
517  _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
518  message,
520  dbus_message_get_path (message) ?
521  dbus_message_get_path (message) :
522  "no path",
523  dbus_message_get_interface (message) ?
524  dbus_message_get_interface (message) :
525  "no interface",
526  dbus_message_get_member (message) ?
527  dbus_message_get_member (message) :
528  "no member",
529  dbus_message_get_signature (message),
531  connection,
532  connection->n_incoming);
533 
534  _dbus_message_trace_ref (message, -1, -1,
535  "_dbus_conection_queue_received_message_link");
536 }
537 
546 void
548  DBusList *link)
549 {
550  HAVE_LOCK_CHECK (connection);
551 
552  _dbus_list_append_link (&connection->incoming_messages, link);
553 
554  connection->n_incoming += 1;
555 
556  _dbus_connection_wakeup_mainloop (connection);
557 
558  _dbus_message_trace_ref (link->data, -1, -1,
559  "_dbus_connection_queue_synthesized_message_link");
560 
561  _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
562  link->data, connection, connection->n_incoming);
563 }
564 
565 
575 {
576  HAVE_LOCK_CHECK (connection);
577  return connection->outgoing_messages != NULL;
578 }
579 
591 {
592  dbus_bool_t v;
593 
594  _dbus_return_val_if_fail (connection != NULL, FALSE);
595 
596  CONNECTION_LOCK (connection);
598  CONNECTION_UNLOCK (connection);
599 
600  return v;
601 }
602 
612 {
613  HAVE_LOCK_CHECK (connection);
614 
615  return _dbus_list_get_last (&connection->outgoing_messages);
616 }
617 
626 void
628  DBusMessage *message)
629 {
630  DBusList *link;
631 
632  HAVE_LOCK_CHECK (connection);
633 
634  /* This can be called before we even complete authentication, since
635  * it's called on disconnect to clean up the outgoing queue.
636  * It's also called as we successfully send each message.
637  */
638 
639  link = _dbus_list_get_last_link (&connection->outgoing_messages);
640  _dbus_assert (link != NULL);
641  _dbus_assert (link->data == message);
642 
643  _dbus_list_unlink (&connection->outgoing_messages,
644  link);
645  _dbus_list_prepend_link (&connection->expired_messages, link);
646 
647  connection->n_outgoing -= 1;
648 
649  _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
650  message,
652  dbus_message_get_path (message) ?
653  dbus_message_get_path (message) :
654  "no path",
655  dbus_message_get_interface (message) ?
656  dbus_message_get_interface (message) :
657  "no interface",
658  dbus_message_get_member (message) ?
659  dbus_message_get_member (message) :
660  "no member",
661  dbus_message_get_signature (message),
662  connection, connection->n_outgoing);
663 
664  /* It's OK that in principle we call the notify function, because for the
665  * outgoing limit, there isn't one */
666  _dbus_message_remove_counter (message, connection->outgoing_counter);
667 
668  /* The message will actually be unreffed when we unlock */
669 }
670 
673  DBusWatch *watch);
675 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
676  DBusWatch *watch);
678 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
679  DBusWatch *watch,
680  dbus_bool_t enabled);
681 
682 static dbus_bool_t
683 protected_change_watch (DBusConnection *connection,
684  DBusWatch *watch,
685  DBusWatchAddFunction add_function,
686  DBusWatchRemoveFunction remove_function,
687  DBusWatchToggleFunction toggle_function,
688  dbus_bool_t enabled)
689 {
690  dbus_bool_t retval;
691 
692  HAVE_LOCK_CHECK (connection);
693 
694  /* The original purpose of protected_change_watch() was to hold a
695  * ref on the connection while dropping the connection lock, then
696  * calling out to the app. This was a broken hack that did not
697  * work, since the connection was in a hosed state (no WatchList
698  * field) while calling out.
699  *
700  * So for now we'll just keep the lock while calling out. This means
701  * apps are not allowed to call DBusConnection methods inside a
702  * watch function or they will deadlock.
703  *
704  * The "real fix" is to use the _and_unlock() pattern found
705  * elsewhere in the code, to defer calling out to the app until
706  * we're about to drop locks and return flow of control to the app
707  * anyway.
708  *
709  * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
710  */
711 
712  if (connection->watches)
713  {
714  if (add_function)
715  retval = (* add_function) (connection->watches, watch);
716  else if (remove_function)
717  {
718  retval = TRUE;
719  (* remove_function) (connection->watches, watch);
720  }
721  else
722  {
723  retval = TRUE;
724  (* toggle_function) (connection->watches, watch, enabled);
725  }
726  return retval;
727  }
728  else
729  return FALSE;
730 }
731 
732 
746  DBusWatch *watch)
747 {
748  return protected_change_watch (connection, watch,
750  NULL, NULL, FALSE);
751 }
752 
762 void
764  DBusWatch *watch)
765 {
766  protected_change_watch (connection, watch,
767  NULL,
769  NULL, FALSE);
770 }
771 
782 void
784  DBusWatch *watch,
785  dbus_bool_t enabled)
786 {
787  _dbus_assert (watch != NULL);
788 
789  protected_change_watch (connection, watch,
790  NULL, NULL,
792  enabled);
793 }
794 
797  DBusTimeout *timeout);
800  DBusTimeout *timeout);
803  DBusTimeout *timeout,
804  dbus_bool_t enabled);
805 
806 static dbus_bool_t
807 protected_change_timeout (DBusConnection *connection,
808  DBusTimeout *timeout,
809  DBusTimeoutAddFunction add_function,
810  DBusTimeoutRemoveFunction remove_function,
811  DBusTimeoutToggleFunction toggle_function,
812  dbus_bool_t enabled)
813 {
814  dbus_bool_t retval;
815 
816  HAVE_LOCK_CHECK (connection);
817 
818  /* The original purpose of protected_change_timeout() was to hold a
819  * ref on the connection while dropping the connection lock, then
820  * calling out to the app. This was a broken hack that did not
821  * work, since the connection was in a hosed state (no TimeoutList
822  * field) while calling out.
823  *
824  * So for now we'll just keep the lock while calling out. This means
825  * apps are not allowed to call DBusConnection methods inside a
826  * timeout function or they will deadlock.
827  *
828  * The "real fix" is to use the _and_unlock() pattern found
829  * elsewhere in the code, to defer calling out to the app until
830  * we're about to drop locks and return flow of control to the app
831  * anyway.
832  *
833  * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
834  */
835 
836  if (connection->timeouts)
837  {
838  if (add_function)
839  retval = (* add_function) (connection->timeouts, timeout);
840  else if (remove_function)
841  {
842  retval = TRUE;
843  (* remove_function) (connection->timeouts, timeout);
844  }
845  else
846  {
847  retval = TRUE;
848  (* toggle_function) (connection->timeouts, timeout, enabled);
849  }
850  return retval;
851  }
852  else
853  return FALSE;
854 }
855 
870  DBusTimeout *timeout)
871 {
872  return protected_change_timeout (connection, timeout,
874  NULL, NULL, FALSE);
875 }
876 
886 void
888  DBusTimeout *timeout)
889 {
890  protected_change_timeout (connection, timeout,
891  NULL,
893  NULL, FALSE);
894 }
895 
906 void
908  DBusTimeout *timeout,
909  dbus_bool_t enabled)
910 {
911  protected_change_timeout (connection, timeout,
912  NULL, NULL,
914  enabled);
915 }
916 
917 static dbus_bool_t
918 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
919  DBusPendingCall *pending)
920 {
921  dbus_uint32_t reply_serial;
922  DBusTimeout *timeout;
923 
924  HAVE_LOCK_CHECK (connection);
925 
926  reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
927 
928  _dbus_assert (reply_serial != 0);
929 
930  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
931 
932  if (timeout)
933  {
934  if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
935  return FALSE;
936 
938  reply_serial,
939  pending))
940  {
941  _dbus_connection_remove_timeout_unlocked (connection, timeout);
942 
944  HAVE_LOCK_CHECK (connection);
945  return FALSE;
946  }
947 
949  }
950  else
951  {
953  reply_serial,
954  pending))
955  {
956  HAVE_LOCK_CHECK (connection);
957  return FALSE;
958  }
959  }
960 
962 
963  HAVE_LOCK_CHECK (connection);
964 
965  return TRUE;
966 }
967 
968 static void
969 free_pending_call_on_hash_removal (void *data)
970 {
971  DBusPendingCall *pending;
972  DBusConnection *connection;
973 
974  if (data == NULL)
975  return;
976 
977  pending = data;
978 
979  connection = _dbus_pending_call_get_connection_unlocked (pending);
980 
981  HAVE_LOCK_CHECK (connection);
982 
984  {
987 
989  }
990 
991  /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock
992  * here, but the pending call finalizer could in principle call out to
993  * application code so we pretty much have to... some larger code reorg
994  * might be needed.
995  */
996  _dbus_connection_ref_unlocked (connection);
998  CONNECTION_LOCK (connection);
999  _dbus_connection_unref_unlocked (connection);
1000 }
1001 
1002 static void
1003 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
1004  DBusPendingCall *pending)
1005 {
1006  /* This ends up unlocking to call the pending call finalizer, which is unexpected to
1007  * say the least.
1008  */
1011 }
1012 
1013 static void
1014 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
1015  DBusPendingCall *pending)
1016 {
1017  /* The idea here is to avoid finalizing the pending call
1018  * with the lock held, since there's a destroy notifier
1019  * in pending call that goes out to application code.
1020  *
1021  * There's an extra unlock inside the hash table
1022  * "free pending call" function FIXME...
1023  */
1027 
1031 
1033 
1035 }
1036 
1045 void
1047  DBusPendingCall *pending)
1048 {
1049  CONNECTION_LOCK (connection);
1050  _dbus_connection_detach_pending_call_and_unlock (connection, pending);
1051 }
1052 
1062 static dbus_bool_t
1063 _dbus_connection_acquire_io_path (DBusConnection *connection,
1064  int timeout_milliseconds)
1065 {
1066  dbus_bool_t we_acquired;
1067 
1068  HAVE_LOCK_CHECK (connection);
1069 
1070  /* We don't want the connection to vanish */
1071  _dbus_connection_ref_unlocked (connection);
1072 
1073  /* We will only touch io_path_acquired which is protected by our mutex */
1074  CONNECTION_UNLOCK (connection);
1075 
1076  _dbus_verbose ("locking io_path_mutex\n");
1077  _dbus_cmutex_lock (connection->io_path_mutex);
1078 
1079  _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
1080  connection->io_path_acquired, timeout_milliseconds);
1081 
1082  we_acquired = FALSE;
1083 
1084  if (connection->io_path_acquired)
1085  {
1086  if (timeout_milliseconds != -1)
1087  {
1088  _dbus_verbose ("waiting %d for IO path to be acquirable\n",
1089  timeout_milliseconds);
1090 
1091  if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
1092  connection->io_path_mutex,
1093  timeout_milliseconds))
1094  {
1095  /* We timed out before anyone signaled. */
1096  /* (writing the loop to handle the !timedout case by
1097  * waiting longer if needed is a pain since dbus
1098  * wraps pthread_cond_timedwait to take a relative
1099  * time instead of absolute, something kind of stupid
1100  * on our part. for now it doesn't matter, we will just
1101  * end up back here eventually.)
1102  */
1103  }
1104  }
1105  else
1106  {
1107  while (connection->io_path_acquired)
1108  {
1109  _dbus_verbose ("waiting for IO path to be acquirable\n");
1110  _dbus_condvar_wait (connection->io_path_cond,
1111  connection->io_path_mutex);
1112  }
1113  }
1114  }
1115 
1116  if (!connection->io_path_acquired)
1117  {
1118  we_acquired = TRUE;
1119  connection->io_path_acquired = TRUE;
1120  }
1121 
1122  _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
1123  connection->io_path_acquired, we_acquired);
1124 
1125  _dbus_verbose ("unlocking io_path_mutex\n");
1126  _dbus_cmutex_unlock (connection->io_path_mutex);
1127 
1128  CONNECTION_LOCK (connection);
1129 
1130  HAVE_LOCK_CHECK (connection);
1131 
1132  _dbus_connection_unref_unlocked (connection);
1133 
1134  return we_acquired;
1135 }
1136 
1144 static void
1145 _dbus_connection_release_io_path (DBusConnection *connection)
1146 {
1147  HAVE_LOCK_CHECK (connection);
1148 
1149  _dbus_verbose ("locking io_path_mutex\n");
1150  _dbus_cmutex_lock (connection->io_path_mutex);
1151 
1152  _dbus_assert (connection->io_path_acquired);
1153 
1154  _dbus_verbose ("start connection->io_path_acquired = %d\n",
1155  connection->io_path_acquired);
1156 
1157  connection->io_path_acquired = FALSE;
1158  _dbus_condvar_wake_one (connection->io_path_cond);
1159 
1160  _dbus_verbose ("unlocking io_path_mutex\n");
1161  _dbus_cmutex_unlock (connection->io_path_mutex);
1162 }
1163 
1199 void
1201  DBusPendingCall *pending,
1202  unsigned int flags,
1203  int timeout_milliseconds)
1204 {
1205  _dbus_verbose ("start\n");
1206 
1207  HAVE_LOCK_CHECK (connection);
1208 
1209  if (connection->n_outgoing == 0)
1210  flags &= ~DBUS_ITERATION_DO_WRITING;
1211 
1212  if (_dbus_connection_acquire_io_path (connection,
1213  (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
1214  {
1215  HAVE_LOCK_CHECK (connection);
1216 
1217  if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
1218  {
1219  _dbus_verbose ("pending call completed while acquiring I/O path");
1220  }
1221  else if ( (pending != NULL) &&
1222  _dbus_connection_peek_for_reply_unlocked (connection,
1224  {
1225  _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
1226  }
1227  else
1228  {
1230  flags, timeout_milliseconds);
1231  }
1232 
1233  _dbus_connection_release_io_path (connection);
1234  }
1235 
1236  HAVE_LOCK_CHECK (connection);
1237 
1238  _dbus_verbose ("end\n");
1239 }
1240 
1252 {
1253  DBusConnection *connection;
1254  DBusWatchList *watch_list;
1255  DBusTimeoutList *timeout_list;
1256  DBusHashTable *pending_replies;
1257  DBusList *disconnect_link;
1258  DBusMessage *disconnect_message;
1259  DBusCounter *outgoing_counter;
1260  DBusObjectTree *objects;
1261 
1262  watch_list = NULL;
1263  connection = NULL;
1264  pending_replies = NULL;
1265  timeout_list = NULL;
1266  disconnect_link = NULL;
1267  disconnect_message = NULL;
1268  outgoing_counter = NULL;
1269  objects = NULL;
1270 
1271  watch_list = _dbus_watch_list_new ();
1272  if (watch_list == NULL)
1273  goto error;
1274 
1275  timeout_list = _dbus_timeout_list_new ();
1276  if (timeout_list == NULL)
1277  goto error;
1278 
1279  pending_replies =
1281  NULL,
1282  (DBusFreeFunction)free_pending_call_on_hash_removal);
1283  if (pending_replies == NULL)
1284  goto error;
1285 
1286  connection = dbus_new0 (DBusConnection, 1);
1287  if (connection == NULL)
1288  goto error;
1289 
1290  _dbus_rmutex_new_at_location (&connection->mutex);
1291  if (connection->mutex == NULL)
1292  goto error;
1293 
1295  if (connection->io_path_mutex == NULL)
1296  goto error;
1297 
1299  if (connection->dispatch_mutex == NULL)
1300  goto error;
1301 
1303  if (connection->dispatch_cond == NULL)
1304  goto error;
1305 
1307  if (connection->io_path_cond == NULL)
1308  goto error;
1309 
1311  if (connection->slot_mutex == NULL)
1312  goto error;
1313 
1314  disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
1316  "Disconnected");
1317 
1318  if (disconnect_message == NULL)
1319  goto error;
1320 
1321  disconnect_link = _dbus_list_alloc_link (disconnect_message);
1322  if (disconnect_link == NULL)
1323  goto error;
1324 
1325  outgoing_counter = _dbus_counter_new ();
1326  if (outgoing_counter == NULL)
1327  goto error;
1328 
1329  objects = _dbus_object_tree_new (connection);
1330  if (objects == NULL)
1331  goto error;
1332 
1333  if (_dbus_atomic_get (&_dbus_modify_sigpipe) != 0)
1335 
1336  /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
1337  _dbus_atomic_inc (&connection->refcount);
1338  connection->transport = transport;
1339  connection->watches = watch_list;
1340  connection->timeouts = timeout_list;
1341  connection->pending_replies = pending_replies;
1342  connection->outgoing_counter = outgoing_counter;
1343  connection->filter_list = NULL;
1344  connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
1345  connection->objects = objects;
1346  connection->exit_on_disconnect = FALSE;
1347  connection->shareable = FALSE;
1348  connection->builtin_filters_enabled = TRUE;
1349  connection->route_peer_messages = FALSE;
1350  connection->disconnected_message_arrived = FALSE;
1351  connection->disconnected_message_processed = FALSE;
1352 
1353 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
1354  connection->generation = _dbus_current_generation;
1355 #endif
1356 
1357  _dbus_data_slot_list_init (&connection->slot_list);
1358 
1359  connection->client_serial = 1;
1360 
1361  connection->disconnect_message_link = disconnect_link;
1362 
1363  CONNECTION_LOCK (connection);
1364 
1365  if (!_dbus_transport_set_connection (transport, connection))
1366  {
1367  CONNECTION_UNLOCK (connection);
1368 
1369  goto error;
1370  }
1371 
1372  _dbus_transport_ref (transport);
1373 
1374  CONNECTION_UNLOCK (connection);
1375 
1376  _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
1377  return connection;
1378 
1379  error:
1380  if (disconnect_message != NULL)
1381  dbus_message_unref (disconnect_message);
1382 
1383  if (disconnect_link != NULL)
1384  _dbus_list_free_link (disconnect_link);
1385 
1386  if (connection != NULL)
1387  {
1390  _dbus_rmutex_free_at_location (&connection->mutex);
1394  dbus_free (connection);
1395  }
1396  if (pending_replies)
1397  _dbus_hash_table_unref (pending_replies);
1398 
1399  if (watch_list)
1400  _dbus_watch_list_free (watch_list);
1401 
1402  if (timeout_list)
1403  _dbus_timeout_list_free (timeout_list);
1404 
1405  if (outgoing_counter)
1406  _dbus_counter_unref (outgoing_counter);
1407 
1408  if (objects)
1409  _dbus_object_tree_unref (objects);
1410 
1411  return NULL;
1412 }
1413 
1423 {
1424  dbus_int32_t old_refcount;
1425 
1426  _dbus_assert (connection != NULL);
1427  _dbus_assert (connection->generation == _dbus_current_generation);
1428 
1429  HAVE_LOCK_CHECK (connection);
1430 
1431  old_refcount = _dbus_atomic_inc (&connection->refcount);
1432  _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
1433  "ref_unlocked");
1434 
1435  return connection;
1436 }
1437 
1444 void
1446 {
1447  dbus_int32_t old_refcount;
1448 
1449  HAVE_LOCK_CHECK (connection);
1450 
1451  _dbus_assert (connection != NULL);
1452 
1453  old_refcount = _dbus_atomic_dec (&connection->refcount);
1454 
1455  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
1456  "unref_unlocked");
1457 
1458  if (old_refcount == 1)
1459  _dbus_connection_last_unref (connection);
1460 }
1461 
1471 dbus_uint32_t
1473 {
1474  dbus_uint32_t serial;
1475 
1476  serial = connection->client_serial++;
1477 
1478  if (connection->client_serial == 0)
1479  connection->client_serial = 1;
1480 
1481  return serial;
1482 }
1483 
1499  unsigned int condition,
1500  void *data)
1501 {
1502  DBusConnection *connection;
1503  dbus_bool_t retval;
1504  DBusDispatchStatus status;
1505 
1506  connection = data;
1507 
1508  _dbus_verbose ("start\n");
1509 
1510  CONNECTION_LOCK (connection);
1511 
1512  if (!_dbus_connection_acquire_io_path (connection, 1))
1513  {
1514  /* another thread is handling the message */
1515  CONNECTION_UNLOCK (connection);
1516  return TRUE;
1517  }
1518 
1519  HAVE_LOCK_CHECK (connection);
1520  retval = _dbus_transport_handle_watch (connection->transport,
1521  watch, condition);
1522 
1523  _dbus_connection_release_io_path (connection);
1524 
1525  HAVE_LOCK_CHECK (connection);
1526 
1527  _dbus_verbose ("middle\n");
1528 
1529  status = _dbus_connection_get_dispatch_status_unlocked (connection);
1530 
1531  /* this calls out to user code */
1532  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
1533 
1534  _dbus_verbose ("end\n");
1535 
1536  return retval;
1537 }
1538 
1539 /* Protected by _DBUS_LOCK (shared_connections) */
1540 static DBusHashTable *shared_connections = NULL;
1541 static DBusList *shared_connections_no_guid = NULL;
1542 
1543 static void
1544 close_connection_on_shutdown (DBusConnection *connection)
1545 {
1546  DBusMessage *message;
1547 
1548  dbus_connection_ref (connection);
1550 
1551  /* Churn through to the Disconnected message */
1552  while ((message = dbus_connection_pop_message (connection)))
1553  {
1554  dbus_message_unref (message);
1555  }
1556  dbus_connection_unref (connection);
1557 }
1558 
1559 static void
1560 shared_connections_shutdown (void *data)
1561 {
1562  int n_entries;
1563 
1564  if (!_DBUS_LOCK (shared_connections))
1565  {
1566  /* We'd have initialized locks before adding anything, so there
1567  * can't be anything there. */
1568  return;
1569  }
1570 
1571  /* This is a little bit unpleasant... better ideas? */
1572  while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
1573  {
1574  DBusConnection *connection;
1575  DBusHashIter iter;
1576 
1577  _dbus_hash_iter_init (shared_connections, &iter);
1578  _dbus_hash_iter_next (&iter);
1579 
1580  connection = _dbus_hash_iter_get_value (&iter);
1581 
1582  _DBUS_UNLOCK (shared_connections);
1583  close_connection_on_shutdown (connection);
1584  if (!_DBUS_LOCK (shared_connections))
1585  _dbus_assert_not_reached ("global locks were already initialized");
1586 
1587  /* The connection should now be dead and not in our hash ... */
1588  _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
1589  }
1590 
1591  _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
1592 
1593  _dbus_hash_table_unref (shared_connections);
1594  shared_connections = NULL;
1595 
1596  if (shared_connections_no_guid != NULL)
1597  {
1598  DBusConnection *connection;
1599  connection = _dbus_list_pop_first (&shared_connections_no_guid);
1600  while (connection != NULL)
1601  {
1602  _DBUS_UNLOCK (shared_connections);
1603  close_connection_on_shutdown (connection);
1604  if (!_DBUS_LOCK (shared_connections))
1605  _dbus_assert_not_reached ("global locks were already initialized");
1606  connection = _dbus_list_pop_first (&shared_connections_no_guid);
1607  }
1608  }
1609 
1610  shared_connections_no_guid = NULL;
1611 
1612  _DBUS_UNLOCK (shared_connections);
1613 }
1614 
1615 static dbus_bool_t
1616 connection_lookup_shared (DBusAddressEntry *entry,
1617  DBusConnection **result)
1618 {
1619  _dbus_verbose ("checking for existing connection\n");
1620 
1621  *result = NULL;
1622 
1623  if (!_DBUS_LOCK (shared_connections))
1624  {
1625  /* If it was shared, we'd have initialized global locks when we put
1626  * it in shared_connections. */
1627  return FALSE;
1628  }
1629 
1630  if (shared_connections == NULL)
1631  {
1632  _dbus_verbose ("creating shared_connections hash table\n");
1633 
1634  shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
1635  dbus_free,
1636  NULL);
1637  if (shared_connections == NULL)
1638  {
1639  _DBUS_UNLOCK (shared_connections);
1640  return FALSE;
1641  }
1642 
1643  if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
1644  {
1645  _dbus_hash_table_unref (shared_connections);
1646  shared_connections = NULL;
1647  _DBUS_UNLOCK (shared_connections);
1648  return FALSE;
1649  }
1650 
1651  _dbus_verbose (" successfully created shared_connections\n");
1652 
1653  _DBUS_UNLOCK (shared_connections);
1654  return TRUE; /* no point looking up in the hash we just made */
1655  }
1656  else
1657  {
1658  const char *guid;
1659 
1660  guid = dbus_address_entry_get_value (entry, "guid");
1661 
1662  if (guid != NULL)
1663  {
1664  DBusConnection *connection;
1665 
1666  connection = _dbus_hash_table_lookup_string (shared_connections,
1667  guid);
1668 
1669  if (connection)
1670  {
1671  /* The DBusConnection can't be finalized without taking
1672  * the shared_connections lock to remove it from the
1673  * hash. So it's safe to ref the connection here.
1674  * However, it may be disconnected if the Disconnected
1675  * message hasn't been processed yet, in which case we
1676  * want to pretend it isn't in the hash and avoid
1677  * returning it.
1678  *
1679  * The idea is to avoid ever returning a disconnected connection
1680  * from dbus_connection_open(). We could just synchronously
1681  * drop our shared ref to the connection on connection disconnect,
1682  * and then assert here that the connection is connected, but
1683  * that causes reentrancy headaches.
1684  */
1685  CONNECTION_LOCK (connection);
1686  if (_dbus_connection_get_is_connected_unlocked (connection))
1687  {
1688  _dbus_connection_ref_unlocked (connection);
1689  *result = connection;
1690  _dbus_verbose ("looked up existing connection to server guid %s\n",
1691  guid);
1692  }
1693  else
1694  {
1695  _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
1696  guid);
1697  }
1698  CONNECTION_UNLOCK (connection);
1699  }
1700  }
1701 
1702  _DBUS_UNLOCK (shared_connections);
1703  return TRUE;
1704  }
1705 }
1706 
1707 static dbus_bool_t
1708 connection_record_shared_unlocked (DBusConnection *connection,
1709  const char *guid)
1710 {
1711  char *guid_key;
1712  char *guid_in_connection;
1713 
1714  HAVE_LOCK_CHECK (connection);
1715  _dbus_assert (connection->server_guid == NULL);
1716  _dbus_assert (connection->shareable);
1717 
1718  /* get a hard ref on this connection, even if
1719  * we won't in fact store it in the hash, we still
1720  * need to hold a ref on it until it's disconnected.
1721  */
1722  _dbus_connection_ref_unlocked (connection);
1723 
1724  if (guid == NULL)
1725  {
1726  if (!_DBUS_LOCK (shared_connections))
1727  return FALSE;
1728 
1729  if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
1730  {
1731  _DBUS_UNLOCK (shared_connections);
1732  return FALSE;
1733  }
1734 
1735  _DBUS_UNLOCK (shared_connections);
1736  return TRUE; /* don't store in the hash */
1737  }
1738 
1739  /* A separate copy of the key is required in the hash table, because
1740  * we don't have a lock on the connection when we are doing a hash
1741  * lookup.
1742  */
1743 
1744  guid_key = _dbus_strdup (guid);
1745  if (guid_key == NULL)
1746  return FALSE;
1747 
1748  guid_in_connection = _dbus_strdup (guid);
1749  if (guid_in_connection == NULL)
1750  {
1751  dbus_free (guid_key);
1752  return FALSE;
1753  }
1754 
1755  if (!_DBUS_LOCK (shared_connections))
1756  {
1757  dbus_free (guid_in_connection);
1758  dbus_free (guid_key);
1759  return FALSE;
1760  }
1761 
1762  _dbus_assert (shared_connections != NULL);
1763 
1764  if (!_dbus_hash_table_insert_string (shared_connections,
1765  guid_key, connection))
1766  {
1767  dbus_free (guid_key);
1768  dbus_free (guid_in_connection);
1769  _DBUS_UNLOCK (shared_connections);
1770  return FALSE;
1771  }
1772 
1773  connection->server_guid = guid_in_connection;
1774 
1775  _dbus_verbose ("stored connection to %s to be shared\n",
1776  connection->server_guid);
1777 
1778  _DBUS_UNLOCK (shared_connections);
1779 
1780  _dbus_assert (connection->server_guid != NULL);
1781 
1782  return TRUE;
1783 }
1784 
1785 static void
1786 connection_forget_shared_unlocked (DBusConnection *connection)
1787 {
1788  HAVE_LOCK_CHECK (connection);
1789 
1790  if (!connection->shareable)
1791  return;
1792 
1793  if (!_DBUS_LOCK (shared_connections))
1794  {
1795  /* If it was shared, we'd have initialized global locks when we put
1796  * it in the table; so it can't be there. */
1797  return;
1798  }
1799 
1800  if (connection->server_guid != NULL)
1801  {
1802  _dbus_verbose ("dropping connection to %s out of the shared table\n",
1803  connection->server_guid);
1804 
1805  if (!_dbus_hash_table_remove_string (shared_connections,
1806  connection->server_guid))
1807  _dbus_assert_not_reached ("connection was not in the shared table");
1808 
1809  dbus_free (connection->server_guid);
1810  connection->server_guid = NULL;
1811  }
1812  else
1813  {
1814  _dbus_list_remove (&shared_connections_no_guid, connection);
1815  }
1816 
1817  _DBUS_UNLOCK (shared_connections);
1818 
1819  /* remove our reference held on all shareable connections */
1820  _dbus_connection_unref_unlocked (connection);
1821 }
1822 
1823 static DBusConnection*
1824 connection_try_from_address_entry (DBusAddressEntry *entry,
1825  DBusError *error)
1826 {
1827  DBusTransport *transport;
1828  DBusConnection *connection;
1829 
1830  transport = _dbus_transport_open (entry, error);
1831 
1832  if (transport == NULL)
1833  {
1834  _DBUS_ASSERT_ERROR_IS_SET (error);
1835  return NULL;
1836  }
1837 
1838  connection = _dbus_connection_new_for_transport (transport);
1839 
1840  _dbus_transport_unref (transport);
1841 
1842  if (connection == NULL)
1843  {
1844  _DBUS_SET_OOM (error);
1845  return NULL;
1846  }
1847 
1848 #ifndef DBUS_DISABLE_CHECKS
1849  _dbus_assert (!connection->have_connection_lock);
1850 #endif
1851  return connection;
1852 }
1853 
1854 /*
1855  * If the shared parameter is true, then any existing connection will
1856  * be used (and if a new connection is created, it will be available
1857  * for use by others). If the shared parameter is false, a new
1858  * connection will always be created, and the new connection will
1859  * never be returned to other callers.
1860  *
1861  * @param address the address
1862  * @param shared whether the connection is shared or private
1863  * @param error error return
1864  * @returns the connection or #NULL on error
1865  */
1866 static DBusConnection*
1867 _dbus_connection_open_internal (const char *address,
1868  dbus_bool_t shared,
1869  DBusError *error)
1870 {
1871  DBusConnection *connection;
1872  DBusAddressEntry **entries;
1873  DBusError tmp_error = DBUS_ERROR_INIT;
1874  DBusError first_error = DBUS_ERROR_INIT;
1875  int len, i;
1876 
1877  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1878 
1879  _dbus_verbose ("opening %s connection to: %s\n",
1880  shared ? "shared" : "private", address);
1881 
1882  if (!dbus_parse_address (address, &entries, &len, error))
1883  return NULL;
1884 
1885  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1886 
1887  connection = NULL;
1888 
1889  for (i = 0; i < len; i++)
1890  {
1891  if (shared)
1892  {
1893  if (!connection_lookup_shared (entries[i], &connection))
1894  _DBUS_SET_OOM (&tmp_error);
1895  }
1896 
1897  if (connection == NULL)
1898  {
1899  connection = connection_try_from_address_entry (entries[i],
1900  &tmp_error);
1901 
1902  if (connection != NULL && shared)
1903  {
1904  const char *guid;
1905 
1906  connection->shareable = TRUE;
1907 
1908  /* guid may be NULL */
1909  guid = dbus_address_entry_get_value (entries[i], "guid");
1910 
1911  CONNECTION_LOCK (connection);
1912 
1913  if (!connection_record_shared_unlocked (connection, guid))
1914  {
1915  _DBUS_SET_OOM (&tmp_error);
1916  _dbus_connection_close_possibly_shared_and_unlock (connection);
1917  dbus_connection_unref (connection);
1918  connection = NULL;
1919  }
1920  else
1921  CONNECTION_UNLOCK (connection);
1922  }
1923  }
1924 
1925  if (connection)
1926  break;
1927 
1928  _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1929 
1930  if (i == 0)
1931  dbus_move_error (&tmp_error, &first_error);
1932  else
1933  dbus_error_free (&tmp_error);
1934  }
1935 
1936  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1937  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1938 
1939  if (connection == NULL)
1940  {
1941  _DBUS_ASSERT_ERROR_IS_SET (&first_error);
1942  dbus_move_error (&first_error, error);
1943  }
1944  else
1945  dbus_error_free (&first_error);
1946 
1947  dbus_address_entries_free (entries);
1948  return connection;
1949 }
1950 
1959 void
1961 {
1962  _dbus_assert (connection != NULL);
1963  _dbus_assert (connection->generation == _dbus_current_generation);
1964 
1965  CONNECTION_LOCK (connection);
1966  _dbus_connection_close_possibly_shared_and_unlock (connection);
1967 }
1968 
1969 static DBusPreallocatedSend*
1970 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
1971 {
1972  DBusPreallocatedSend *preallocated;
1973 
1974  HAVE_LOCK_CHECK (connection);
1975 
1976  _dbus_assert (connection != NULL);
1977 
1978  preallocated = dbus_new (DBusPreallocatedSend, 1);
1979  if (preallocated == NULL)
1980  return NULL;
1981 
1982  preallocated->queue_link = _dbus_list_alloc_link (NULL);
1983  if (preallocated->queue_link == NULL)
1984  goto failed_0;
1985 
1986  preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
1987  if (preallocated->counter_link == NULL)
1988  goto failed_1;
1989 
1990  _dbus_counter_ref (preallocated->counter_link->data);
1991 
1992  preallocated->connection = connection;
1993 
1994  return preallocated;
1995 
1996  failed_1:
1997  _dbus_list_free_link (preallocated->queue_link);
1998  failed_0:
1999  dbus_free (preallocated);
2000 
2001  return NULL;
2002 }
2003 
2004 /* Called with lock held, does not update dispatch status */
2005 static void
2006 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
2007  DBusPreallocatedSend *preallocated,
2008  DBusMessage *message,
2009  dbus_uint32_t *client_serial)
2010 {
2011  dbus_uint32_t serial;
2012 
2013  preallocated->queue_link->data = message;
2015  preallocated->queue_link);
2016 
2017  /* It's OK that we'll never call the notify function, because for the
2018  * outgoing limit, there isn't one */
2020  preallocated->counter_link);
2021 
2022  dbus_free (preallocated);
2023  preallocated = NULL;
2024 
2025  dbus_message_ref (message);
2026 
2027  connection->n_outgoing += 1;
2028 
2029  _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
2030  message,
2032  dbus_message_get_path (message) ?
2033  dbus_message_get_path (message) :
2034  "no path",
2035  dbus_message_get_interface (message) ?
2036  dbus_message_get_interface (message) :
2037  "no interface",
2038  dbus_message_get_member (message) ?
2039  dbus_message_get_member (message) :
2040  "no member",
2041  dbus_message_get_signature (message),
2042  dbus_message_get_destination (message) ?
2043  dbus_message_get_destination (message) :
2044  "null",
2045  connection,
2046  connection->n_outgoing);
2047 
2048  if (dbus_message_get_serial (message) == 0)
2049  {
2050  serial = _dbus_connection_get_next_client_serial (connection);
2051  dbus_message_set_serial (message, serial);
2052  if (client_serial)
2053  *client_serial = serial;
2054  }
2055  else
2056  {
2057  if (client_serial)
2058  *client_serial = dbus_message_get_serial (message);
2059  }
2060 
2061  _dbus_verbose ("Message %p serial is %u\n",
2062  message, dbus_message_get_serial (message));
2063 
2064  dbus_message_lock (message);
2065 
2066  /* Now we need to run an iteration to hopefully just write the messages
2067  * out immediately, and otherwise get them queued up
2068  */
2070  NULL,
2071  DBUS_ITERATION_DO_WRITING,
2072  -1);
2073 
2074  /* If stuff is still queued up, be sure we wake up the main loop */
2075  if (connection->n_outgoing > 0)
2076  _dbus_connection_wakeup_mainloop (connection);
2077 }
2078 
2079 static void
2080 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
2081  DBusPreallocatedSend *preallocated,
2082  DBusMessage *message,
2083  dbus_uint32_t *client_serial)
2084 {
2085  DBusDispatchStatus status;
2086 
2087  HAVE_LOCK_CHECK (connection);
2088 
2089  _dbus_connection_send_preallocated_unlocked_no_update (connection,
2090  preallocated,
2091  message, client_serial);
2092 
2093  _dbus_verbose ("middle\n");
2094  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2095 
2096  /* this calls out to user code */
2097  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2098 }
2099 
2111  DBusMessage *message,
2112  dbus_uint32_t *client_serial)
2113 {
2114  DBusPreallocatedSend *preallocated;
2115 
2116  _dbus_assert (connection != NULL);
2117  _dbus_assert (message != NULL);
2118 
2119  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
2120  if (preallocated == NULL)
2121  {
2122  CONNECTION_UNLOCK (connection);
2123  return FALSE;
2124  }
2125 
2126  _dbus_connection_send_preallocated_and_unlock (connection,
2127  preallocated,
2128  message,
2129  client_serial);
2130  return TRUE;
2131 }
2132 
2157 void
2159 {
2160  dbus_int32_t refcount;
2161 
2162  CONNECTION_LOCK (connection);
2163 
2164  refcount = _dbus_atomic_get (&connection->refcount);
2165  /* The caller should have at least one ref */
2166  _dbus_assert (refcount >= 1);
2167 
2168  if (refcount == 1)
2169  _dbus_connection_close_possibly_shared_and_unlock (connection);
2170  else
2171  CONNECTION_UNLOCK (connection);
2172 }
2173 
2174 
2184 static void
2185 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
2186 {
2187  if (timeout_milliseconds == -1)
2188  _dbus_sleep_milliseconds (1000);
2189  else if (timeout_milliseconds < 100)
2190  ; /* just busy loop */
2191  else if (timeout_milliseconds <= 1000)
2192  _dbus_sleep_milliseconds (timeout_milliseconds / 3);
2193  else
2194  _dbus_sleep_milliseconds (1000);
2195 }
2196 
2197 static DBusMessage *
2198 generate_local_error_message (dbus_uint32_t serial,
2199  const char *error_name,
2200  const char *error_msg)
2201 {
2202  DBusMessage *message;
2204  if (!message)
2205  goto out;
2206 
2207  if (!dbus_message_set_error_name (message, error_name))
2208  {
2209  dbus_message_unref (message);
2210  message = NULL;
2211  goto out;
2212  }
2213 
2214  dbus_message_set_no_reply (message, TRUE);
2215 
2216  if (!dbus_message_set_reply_serial (message,
2217  serial))
2218  {
2219  dbus_message_unref (message);
2220  message = NULL;
2221  goto out;
2222  }
2223 
2224  if (error_msg != NULL)
2225  {
2226  DBusMessageIter iter;
2227 
2228  dbus_message_iter_init_append (message, &iter);
2229  if (!dbus_message_iter_append_basic (&iter,
2231  &error_msg))
2232  {
2233  dbus_message_unref (message);
2234  message = NULL;
2235  goto out;
2236  }
2237  }
2238 
2239  out:
2240  return message;
2241 }
2242 
2243 /*
2244  * Peek the incoming queue to see if we got reply for a specific serial
2245  */
2246 static dbus_bool_t
2247 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
2248  dbus_uint32_t client_serial)
2249 {
2250  DBusList *link;
2251  HAVE_LOCK_CHECK (connection);
2252 
2253  link = _dbus_list_get_first_link (&connection->incoming_messages);
2254 
2255  while (link != NULL)
2256  {
2257  DBusMessage *reply = link->data;
2258 
2259  if (dbus_message_get_reply_serial (reply) == client_serial)
2260  {
2261  _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
2262  return TRUE;
2263  }
2264  link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2265  }
2266 
2267  return FALSE;
2268 }
2269 
2270 /* This is slightly strange since we can pop a message here without
2271  * the dispatch lock.
2272  */
2273 static DBusMessage*
2274 check_for_reply_unlocked (DBusConnection *connection,
2275  dbus_uint32_t client_serial)
2276 {
2277  DBusList *link;
2278 
2279  HAVE_LOCK_CHECK (connection);
2280 
2281  link = _dbus_list_get_first_link (&connection->incoming_messages);
2282 
2283  while (link != NULL)
2284  {
2285  DBusMessage *reply = link->data;
2286 
2287  if (dbus_message_get_reply_serial (reply) == client_serial)
2288  {
2289  _dbus_list_remove_link (&connection->incoming_messages, link);
2290  connection->n_incoming -= 1;
2291  return reply;
2292  }
2293  link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2294  }
2295 
2296  return NULL;
2297 }
2298 
2299 static void
2300 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
2301 {
2302  /* We can't iterate over the hash in the normal way since we'll be
2303  * dropping the lock for each item. So we restart the
2304  * iter each time as we drain the hash table.
2305  */
2306 
2307  while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
2308  {
2309  DBusPendingCall *pending;
2310  DBusHashIter iter;
2311 
2312  _dbus_hash_iter_init (connection->pending_replies, &iter);
2313  _dbus_hash_iter_next (&iter);
2314 
2315  pending = _dbus_hash_iter_get_value (&iter);
2317 
2319  connection);
2320 
2326 
2328  CONNECTION_LOCK (connection);
2329  }
2330  HAVE_LOCK_CHECK (connection);
2331 }
2332 
2333 static void
2334 complete_pending_call_and_unlock (DBusConnection *connection,
2335  DBusPendingCall *pending,
2336  DBusMessage *message)
2337 {
2338  _dbus_pending_call_set_reply_unlocked (pending, message);
2339  _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
2341  _dbus_connection_detach_pending_call_and_unlock (connection, pending);
2342 
2343  /* Must be called unlocked since it invokes app callback */
2345  dbus_pending_call_unref (pending);
2346 }
2347 
2348 static dbus_bool_t
2349 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
2350  DBusPendingCall *pending)
2351 {
2352  DBusMessage *reply;
2353  DBusDispatchStatus status;
2354 
2355  reply = check_for_reply_unlocked (connection,
2357  if (reply != NULL)
2358  {
2359  _dbus_verbose ("checked for reply\n");
2360 
2361  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
2362 
2363  complete_pending_call_and_unlock (connection, pending, reply);
2364  dbus_message_unref (reply);
2365 
2366  CONNECTION_LOCK (connection);
2367  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2368  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2369  dbus_pending_call_unref (pending);
2370 
2371  return TRUE;
2372  }
2373 
2374  return FALSE;
2375 }
2376 
2391 void
2393 {
2394  long start_tv_sec, start_tv_usec;
2395  long tv_sec, tv_usec;
2396  DBusDispatchStatus status;
2397  DBusConnection *connection;
2398  dbus_uint32_t client_serial;
2399  DBusTimeout *timeout;
2400  int timeout_milliseconds, elapsed_milliseconds;
2401 
2402  _dbus_assert (pending != NULL);
2403 
2404  if (dbus_pending_call_get_completed (pending))
2405  return;
2406 
2407  dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
2408 
2409  connection = _dbus_pending_call_get_connection_and_lock (pending);
2410 
2411  /* Flush message queue - note, can affect dispatch status */
2412  _dbus_connection_flush_unlocked (connection);
2413 
2414  client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
2415 
2416  /* note that timeout_milliseconds is limited to a smallish value
2417  * in _dbus_pending_call_new() so overflows aren't possible
2418  * below
2419  */
2420  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
2421  _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
2422  if (timeout)
2423  {
2424  timeout_milliseconds = dbus_timeout_get_interval (timeout);
2425 
2426  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
2427  timeout_milliseconds,
2428  client_serial,
2429  start_tv_sec, start_tv_usec);
2430  }
2431  else
2432  {
2433  timeout_milliseconds = -1;
2434 
2435  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
2436  }
2437 
2438  /* check to see if we already got the data off the socket */
2439  /* from another blocked pending call */
2440  if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2441  return;
2442 
2443  /* Now we wait... */
2444  /* always block at least once as we know we don't have the reply yet */
2446  pending,
2447  DBUS_ITERATION_DO_READING |
2448  DBUS_ITERATION_BLOCK,
2449  timeout_milliseconds);
2450 
2451  recheck_status:
2452 
2453  _dbus_verbose ("top of recheck\n");
2454 
2455  HAVE_LOCK_CHECK (connection);
2456 
2457  /* queue messages and get status */
2458 
2459  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2460 
2461  /* the get_completed() is in case a dispatch() while we were blocking
2462  * got the reply instead of us.
2463  */
2465  {
2466  _dbus_verbose ("Pending call completed by dispatch\n");
2467  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2468  dbus_pending_call_unref (pending);
2469  return;
2470  }
2471 
2472  if (status == DBUS_DISPATCH_DATA_REMAINS)
2473  {
2474  if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2475  return;
2476  }
2477 
2478  _dbus_get_monotonic_time (&tv_sec, &tv_usec);
2479  elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
2480  (tv_usec - start_tv_usec) / 1000;
2481 
2482  if (!_dbus_connection_get_is_connected_unlocked (connection))
2483  {
2484  DBusMessage *error_msg;
2485 
2486  error_msg = generate_local_error_message (client_serial,
2488  "Connection was disconnected before a reply was received");
2489 
2490  /* on OOM error_msg is set to NULL */
2491  complete_pending_call_and_unlock (connection, pending, error_msg);
2492  if (error_msg != NULL)
2493  dbus_message_unref (error_msg);
2494  dbus_pending_call_unref (pending);
2495  return;
2496  }
2497  else if (connection->disconnect_message_link == NULL)
2498  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
2499  else if (timeout == NULL)
2500  {
2501  if (status == DBUS_DISPATCH_NEED_MEMORY)
2502  {
2503  /* Try sleeping a bit, as we aren't sure we need to block for reading,
2504  * we may already have a reply in the buffer and just can't process
2505  * it.
2506  */
2507  _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2508 
2509  _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2510  }
2511  else
2512  {
2513  /* block again, we don't have the reply buffered yet. */
2515  pending,
2516  DBUS_ITERATION_DO_READING |
2517  DBUS_ITERATION_BLOCK,
2518  timeout_milliseconds - elapsed_milliseconds);
2519  }
2520 
2521  goto recheck_status;
2522  }
2523  else if (tv_sec < start_tv_sec)
2524  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
2525  else if (elapsed_milliseconds < timeout_milliseconds)
2526  {
2527  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
2528 
2529  if (status == DBUS_DISPATCH_NEED_MEMORY)
2530  {
2531  /* Try sleeping a bit, as we aren't sure we need to block for reading,
2532  * we may already have a reply in the buffer and just can't process
2533  * it.
2534  */
2535  _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2536 
2537  _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2538  }
2539  else
2540  {
2541  /* block again, we don't have the reply buffered yet. */
2543  pending,
2544  DBUS_ITERATION_DO_READING |
2545  DBUS_ITERATION_BLOCK,
2546  timeout_milliseconds - elapsed_milliseconds);
2547  }
2548 
2549  goto recheck_status;
2550  }
2551 
2552  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
2553  elapsed_milliseconds);
2554 
2556 
2557  /* unlock and call user code */
2558  complete_pending_call_and_unlock (connection, pending, NULL);
2559 
2560  /* update user code on dispatch status */
2561  CONNECTION_LOCK (connection);
2562  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2563  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2564  dbus_pending_call_unref (pending);
2565 }
2566 
2572 int
2574 {
2575  return _dbus_transport_get_pending_fds_count (connection->transport);
2576 }
2577 
2585 void
2587  DBusPendingFdsChangeFunction callback,
2588  void *data)
2589 {
2591  callback, data);
2592 }
2593 
2631 dbus_connection_open (const char *address,
2632  DBusError *error)
2633 {
2634  DBusConnection *connection;
2635 
2636  _dbus_return_val_if_fail (address != NULL, NULL);
2637  _dbus_return_val_if_error_is_set (error, NULL);
2638 
2639  connection = _dbus_connection_open_internal (address,
2640  TRUE,
2641  error);
2642 
2643  return connection;
2644 }
2645 
2674 dbus_connection_open_private (const char *address,
2675  DBusError *error)
2676 {
2677  DBusConnection *connection;
2678 
2679  _dbus_return_val_if_fail (address != NULL, NULL);
2680  _dbus_return_val_if_error_is_set (error, NULL);
2681 
2682  connection = _dbus_connection_open_internal (address,
2683  FALSE,
2684  error);
2685 
2686  return connection;
2687 }
2688 
2697 {
2698  dbus_int32_t old_refcount;
2699 
2700  _dbus_return_val_if_fail (connection != NULL, NULL);
2701  _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
2702  old_refcount = _dbus_atomic_inc (&connection->refcount);
2703  _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
2704  "ref");
2705 
2706  return connection;
2707 }
2708 
2709 static void
2710 free_outgoing_message (void *element,
2711  void *data)
2712 {
2713  DBusMessage *message = element;
2714  DBusConnection *connection = data;
2715 
2716  _dbus_message_remove_counter (message, connection->outgoing_counter);
2717  dbus_message_unref (message);
2718 }
2719 
2720 /* This is run without the mutex held, but after the last reference
2721  * to the connection has been dropped we should have no thread-related
2722  * problems
2723  */
2724 static void
2725 _dbus_connection_last_unref (DBusConnection *connection)
2726 {
2727  DBusList *link;
2728 
2729  _dbus_verbose ("Finalizing connection %p\n", connection);
2730 
2731  _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
2732 
2733  /* You have to disconnect the connection before unref:ing it. Otherwise
2734  * you won't get the disconnected message.
2735  */
2737  _dbus_assert (connection->server_guid == NULL);
2738 
2739  /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
2741 
2746 
2747  _dbus_watch_list_free (connection->watches);
2748  connection->watches = NULL;
2749 
2750  _dbus_timeout_list_free (connection->timeouts);
2751  connection->timeouts = NULL;
2752 
2753  _dbus_data_slot_list_free (&connection->slot_list);
2754 
2755  link = _dbus_list_get_first_link (&connection->filter_list);
2756  while (link != NULL)
2757  {
2758  DBusMessageFilter *filter = link->data;
2759  DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
2760 
2761  filter->function = NULL;
2762  _dbus_message_filter_unref (filter); /* calls app callback */
2763  link->data = NULL;
2764 
2765  link = next;
2766  }
2767  _dbus_list_clear (&connection->filter_list);
2768 
2769  /* ---- Done with stuff that invokes application callbacks */
2770 
2771  _dbus_object_tree_unref (connection->objects);
2772 
2774  connection->pending_replies = NULL;
2775 
2776  _dbus_list_foreach (&connection->outgoing_messages,
2777  free_outgoing_message,
2778  connection);
2779  _dbus_list_clear (&connection->outgoing_messages);
2780 
2783 
2784  _dbus_counter_unref (connection->outgoing_counter);
2785 
2786  _dbus_transport_unref (connection->transport);
2787 
2788  if (connection->disconnect_message_link)
2789  {
2790  DBusMessage *message = connection->disconnect_message_link->data;
2791  dbus_message_unref (message);
2793  }
2794 
2797 
2800 
2802 
2803  _dbus_rmutex_free_at_location (&connection->mutex);
2804 
2805  dbus_free (connection);
2806 }
2807 
2827 void
2829 {
2830  dbus_int32_t old_refcount;
2831 
2832  _dbus_return_if_fail (connection != NULL);
2833  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2834 
2835  old_refcount = _dbus_atomic_dec (&connection->refcount);
2836 
2837  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
2838  "unref");
2839 
2840  if (old_refcount == 1)
2841  {
2842 #ifndef DBUS_DISABLE_CHECKS
2843  if (_dbus_transport_get_is_connected (connection->transport))
2844  {
2845  _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",
2846  connection->shareable ?
2847  "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
2848  "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
2849  return;
2850  }
2851 #endif
2852  _dbus_connection_last_unref (connection);
2853  }
2854 }
2855 
2856 /*
2857  * Note that the transport can disconnect itself (other end drops us)
2858  * and in that case this function never runs. So this function must
2859  * not do anything more than disconnect the transport and update the
2860  * dispatch status.
2861  *
2862  * If the transport self-disconnects, then we assume someone will
2863  * dispatch the connection to cause the dispatch status update.
2864  */
2865 static void
2866 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
2867 {
2868  DBusDispatchStatus status;
2869 
2870  HAVE_LOCK_CHECK (connection);
2871 
2872  _dbus_verbose ("Disconnecting %p\n", connection);
2873 
2874  /* We need to ref because update_dispatch_status_and_unlock will unref
2875  * the connection if it was shared and libdbus was the only remaining
2876  * refcount holder.
2877  */
2878  _dbus_connection_ref_unlocked (connection);
2879 
2880  _dbus_transport_disconnect (connection->transport);
2881 
2882  /* This has the side effect of queuing the disconnect message link
2883  * (unless we don't have enough memory, possibly, so don't assert it).
2884  * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
2885  * should never again return the newly-disconnected connection.
2886  *
2887  * However, we only unref the shared connection and exit_on_disconnect when
2888  * the disconnect message reaches the head of the message queue,
2889  * NOT when it's first queued.
2890  */
2891  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2892 
2893  /* This calls out to user code */
2894  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2895 
2896  /* Could also call out to user code */
2897  dbus_connection_unref (connection);
2898 }
2899 
2942 void
2944 {
2945  _dbus_return_if_fail (connection != NULL);
2946  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2947 
2948  CONNECTION_LOCK (connection);
2949 
2950 #ifndef DBUS_DISABLE_CHECKS
2951  if (connection->shareable)
2952  {
2953  CONNECTION_UNLOCK (connection);
2954 
2955  _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
2956  return;
2957  }
2958 #endif
2959 
2960  _dbus_connection_close_possibly_shared_and_unlock (connection);
2961 }
2962 
2963 static dbus_bool_t
2964 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
2965 {
2966  HAVE_LOCK_CHECK (connection);
2967  return _dbus_transport_get_is_connected (connection->transport);
2968 }
2969 
2985 {
2986  dbus_bool_t res;
2987 
2988  _dbus_return_val_if_fail (connection != NULL, FALSE);
2989 
2990  CONNECTION_LOCK (connection);
2991  res = _dbus_connection_get_is_connected_unlocked (connection);
2992  CONNECTION_UNLOCK (connection);
2993 
2994  return res;
2995 }
2996 
3007 {
3008  dbus_bool_t res;
3009 
3010  _dbus_return_val_if_fail (connection != NULL, FALSE);
3011 
3012  CONNECTION_LOCK (connection);
3013  res = _dbus_transport_try_to_authenticate (connection->transport);
3014  CONNECTION_UNLOCK (connection);
3015 
3016  return res;
3017 }
3018 
3041 {
3042  dbus_bool_t res;
3043 
3044  _dbus_return_val_if_fail (connection != NULL, FALSE);
3045 
3046  CONNECTION_LOCK (connection);
3047  res = _dbus_transport_get_is_anonymous (connection->transport);
3048  CONNECTION_UNLOCK (connection);
3049 
3050  return res;
3051 }
3052 
3084 char*
3086 {
3087  char *id;
3088 
3089  _dbus_return_val_if_fail (connection != NULL, NULL);
3090 
3091  CONNECTION_LOCK (connection);
3093  CONNECTION_UNLOCK (connection);
3094 
3095  return id;
3096 }
3097 
3117  int type)
3118 {
3119  _dbus_return_val_if_fail (connection != NULL, FALSE);
3120 
3121  if (!dbus_type_is_valid (type))
3122  return FALSE;
3123 
3124  if (type != DBUS_TYPE_UNIX_FD)
3125  return TRUE;
3126 
3127 #ifdef HAVE_UNIX_FD_PASSING
3128  {
3129  dbus_bool_t b;
3130 
3131  CONNECTION_LOCK(connection);
3133  CONNECTION_UNLOCK(connection);
3134 
3135  return b;
3136  }
3137 #endif
3138 
3139  return FALSE;
3140 }
3141 
3155 void
3157  dbus_bool_t exit_on_disconnect)
3158 {
3159  _dbus_return_if_fail (connection != NULL);
3160 
3161  CONNECTION_LOCK (connection);
3162  connection->exit_on_disconnect = exit_on_disconnect != FALSE;
3163  CONNECTION_UNLOCK (connection);
3164 }
3165 
3177 {
3178  DBusPreallocatedSend *preallocated;
3179 
3180  _dbus_return_val_if_fail (connection != NULL, NULL);
3181 
3182  CONNECTION_LOCK (connection);
3183 
3184  preallocated =
3185  _dbus_connection_preallocate_send_unlocked (connection);
3186 
3187  CONNECTION_UNLOCK (connection);
3188 
3189  return preallocated;
3190 }
3191 
3201 void
3203  DBusPreallocatedSend *preallocated)
3204 {
3205  _dbus_return_if_fail (connection != NULL);
3206  _dbus_return_if_fail (preallocated != NULL);
3207  _dbus_return_if_fail (connection == preallocated->connection);
3208 
3209  _dbus_list_free_link (preallocated->queue_link);
3210  _dbus_counter_unref (preallocated->counter_link->data);
3211  _dbus_list_free_link (preallocated->counter_link);
3212  dbus_free (preallocated);
3213 }
3214 
3227 void
3229  DBusPreallocatedSend *preallocated,
3230  DBusMessage *message,
3231  dbus_uint32_t *client_serial)
3232 {
3233  _dbus_return_if_fail (connection != NULL);
3234  _dbus_return_if_fail (preallocated != NULL);
3235  _dbus_return_if_fail (message != NULL);
3236  _dbus_return_if_fail (preallocated->connection == connection);
3237  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
3238  dbus_message_get_member (message) != NULL);
3239  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
3240  (dbus_message_get_interface (message) != NULL &&
3241  dbus_message_get_member (message) != NULL));
3242 
3243  CONNECTION_LOCK (connection);
3244 
3245 #ifdef HAVE_UNIX_FD_PASSING
3246 
3247  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3248  message->n_unix_fds > 0)
3249  {
3250  /* Refuse to send fds on a connection that cannot handle
3251  them. Unfortunately we cannot return a proper error here, so
3252  the best we can is just return. */
3253  CONNECTION_UNLOCK (connection);
3254  return;
3255  }
3256 
3257 #endif
3258 
3259  _dbus_connection_send_preallocated_and_unlock (connection,
3260  preallocated,
3261  message, client_serial);
3262 }
3263 
3264 static dbus_bool_t
3265 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
3266  DBusMessage *message,
3267  dbus_uint32_t *client_serial)
3268 {
3269  DBusPreallocatedSend *preallocated;
3270 
3271  _dbus_assert (connection != NULL);
3272  _dbus_assert (message != NULL);
3273 
3274  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
3275  if (preallocated == NULL)
3276  return FALSE;
3277 
3278  _dbus_connection_send_preallocated_unlocked_no_update (connection,
3279  preallocated,
3280  message,
3281  client_serial);
3282  return TRUE;
3283 }
3284 
3314  DBusMessage *message,
3315  dbus_uint32_t *serial)
3316 {
3317  _dbus_return_val_if_fail (connection != NULL, FALSE);
3318  _dbus_return_val_if_fail (message != NULL, FALSE);
3319 
3320  CONNECTION_LOCK (connection);
3321 
3322 #ifdef HAVE_UNIX_FD_PASSING
3323 
3324  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3325  message->n_unix_fds > 0)
3326  {
3327  /* Refuse to send fds on a connection that cannot handle
3328  them. Unfortunately we cannot return a proper error here, so
3329  the best we can is just return. */
3330  CONNECTION_UNLOCK (connection);
3331  return FALSE;
3332  }
3333 
3334 #endif
3335 
3336  return _dbus_connection_send_and_unlock (connection,
3337  message,
3338  serial);
3339 }
3340 
3341 static dbus_bool_t
3342 reply_handler_timeout (void *data)
3343 {
3344  DBusConnection *connection;
3345  DBusDispatchStatus status;
3346  DBusPendingCall *pending = data;
3347 
3348  connection = _dbus_pending_call_get_connection_and_lock (pending);
3349  _dbus_connection_ref_unlocked (connection);
3350 
3352  connection);
3356 
3357  _dbus_verbose ("middle\n");
3358  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3359 
3360  /* Unlocks, and calls out to user code */
3361  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3362  dbus_connection_unref (connection);
3363 
3364  return TRUE;
3365 }
3366 
3411  DBusMessage *message,
3412  DBusPendingCall **pending_return,
3413  int timeout_milliseconds)
3414 {
3415  DBusPendingCall *pending;
3416  dbus_int32_t serial = -1;
3417  DBusDispatchStatus status;
3418 
3419  _dbus_return_val_if_fail (connection != NULL, FALSE);
3420  _dbus_return_val_if_fail (message != NULL, FALSE);
3421  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3422 
3423  if (pending_return)
3424  *pending_return = NULL;
3425 
3426  CONNECTION_LOCK (connection);
3427 
3428 #ifdef HAVE_UNIX_FD_PASSING
3429 
3430  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3431  message->n_unix_fds > 0)
3432  {
3433  /* Refuse to send fds on a connection that cannot handle
3434  them. Unfortunately we cannot return a proper error here, so
3435  the best we can do is return TRUE but leave *pending_return
3436  as NULL. */
3437  CONNECTION_UNLOCK (connection);
3438  return TRUE;
3439  }
3440 
3441 #endif
3442 
3443  if (!_dbus_connection_get_is_connected_unlocked (connection))
3444  {
3445  CONNECTION_UNLOCK (connection);
3446 
3447  return TRUE;
3448  }
3449 
3450  pending = _dbus_pending_call_new_unlocked (connection,
3451  timeout_milliseconds,
3452  reply_handler_timeout);
3453 
3454  if (pending == NULL)
3455  {
3456  CONNECTION_UNLOCK (connection);
3457  return FALSE;
3458  }
3459 
3460  /* Assign a serial to the message */
3461  serial = dbus_message_get_serial (message);
3462  if (serial == 0)
3463  {
3464  serial = _dbus_connection_get_next_client_serial (connection);
3465  dbus_message_set_serial (message, serial);
3466  }
3467 
3468  if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
3469  goto error;
3470 
3471  /* Insert the serial in the pending replies hash;
3472  * hash takes a refcount on DBusPendingCall.
3473  * Also, add the timeout.
3474  */
3475  if (!_dbus_connection_attach_pending_call_unlocked (connection,
3476  pending))
3477  goto error;
3478 
3479  if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
3480  {
3481  _dbus_connection_detach_pending_call_and_unlock (connection,
3482  pending);
3483  goto error_unlocked;
3484  }
3485 
3486  if (pending_return)
3487  *pending_return = pending; /* hand off refcount */
3488  else
3489  {
3490  _dbus_connection_detach_pending_call_unlocked (connection, pending);
3491  /* we still have a ref to the pending call in this case, we unref
3492  * after unlocking, below
3493  */
3494  }
3495 
3496  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3497 
3498  /* this calls out to user code */
3499  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3500 
3501  if (pending_return == NULL)
3502  dbus_pending_call_unref (pending);
3503 
3504  return TRUE;
3505 
3506  error:
3507  CONNECTION_UNLOCK (connection);
3508  error_unlocked:
3509  dbus_pending_call_unref (pending);
3510  return FALSE;
3511 }
3512 
3545 DBusMessage*
3547  DBusMessage *message,
3548  int timeout_milliseconds,
3549  DBusError *error)
3550 {
3551  DBusMessage *reply;
3552  DBusPendingCall *pending;
3553 
3554  _dbus_return_val_if_fail (connection != NULL, NULL);
3555  _dbus_return_val_if_fail (message != NULL, NULL);
3556  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
3557  _dbus_return_val_if_error_is_set (error, NULL);
3558 
3559 #ifdef HAVE_UNIX_FD_PASSING
3560 
3561  CONNECTION_LOCK (connection);
3562  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3563  message->n_unix_fds > 0)
3564  {
3565  CONNECTION_UNLOCK (connection);
3566  dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
3567  return NULL;
3568  }
3569  CONNECTION_UNLOCK (connection);
3570 
3571 #endif
3572 
3573  if (!dbus_connection_send_with_reply (connection, message,
3574  &pending, timeout_milliseconds))
3575  {
3576  _DBUS_SET_OOM (error);
3577  return NULL;
3578  }
3579 
3580  if (pending == NULL)
3581  {
3582  dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
3583  return NULL;
3584  }
3585 
3586  dbus_pending_call_block (pending);
3587 
3588  reply = dbus_pending_call_steal_reply (pending);
3589  dbus_pending_call_unref (pending);
3590 
3591  /* call_complete_and_unlock() called from pending_call_block() should
3592  * always fill this in.
3593  */
3594  _dbus_assert (reply != NULL);
3595 
3596  if (dbus_set_error_from_message (error, reply))
3597  {
3598  dbus_message_unref (reply);
3599  return NULL;
3600  }
3601  else
3602  return reply;
3603 }
3604 
3613 static DBusDispatchStatus
3614 _dbus_connection_flush_unlocked (DBusConnection *connection)
3615 {
3616  /* We have to specify DBUS_ITERATION_DO_READING here because
3617  * otherwise we could have two apps deadlock if they are both doing
3618  * a flush(), and the kernel buffers fill up. This could change the
3619  * dispatch status.
3620  */
3621  DBusDispatchStatus status;
3622 
3623  HAVE_LOCK_CHECK (connection);
3624 
3625  while (connection->n_outgoing > 0 &&
3626  _dbus_connection_get_is_connected_unlocked (connection))
3627  {
3628  _dbus_verbose ("doing iteration in\n");
3629  HAVE_LOCK_CHECK (connection);
3631  NULL,
3632  DBUS_ITERATION_DO_READING |
3633  DBUS_ITERATION_DO_WRITING |
3634  DBUS_ITERATION_BLOCK,
3635  -1);
3636  }
3637 
3638  HAVE_LOCK_CHECK (connection);
3639  _dbus_verbose ("middle\n");
3640  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3641 
3642  HAVE_LOCK_CHECK (connection);
3643  return status;
3644 }
3645 
3651 void
3653 {
3654  /* We have to specify DBUS_ITERATION_DO_READING here because
3655  * otherwise we could have two apps deadlock if they are both doing
3656  * a flush(), and the kernel buffers fill up. This could change the
3657  * dispatch status.
3658  */
3659  DBusDispatchStatus status;
3660 
3661  _dbus_return_if_fail (connection != NULL);
3662 
3663  CONNECTION_LOCK (connection);
3664 
3665  status = _dbus_connection_flush_unlocked (connection);
3666 
3667  HAVE_LOCK_CHECK (connection);
3668  /* Unlocks and calls out to user code */
3669  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3670 
3671  _dbus_verbose ("end\n");
3672 }
3673 
3684 static dbus_bool_t
3685 _dbus_connection_read_write_dispatch (DBusConnection *connection,
3686  int timeout_milliseconds,
3687  dbus_bool_t dispatch)
3688 {
3689  DBusDispatchStatus dstatus;
3690  dbus_bool_t progress_possible;
3691 
3692  /* Need to grab a ref here in case we're a private connection and
3693  * the user drops the last ref in a handler we call; see bug
3694  * https://bugs.freedesktop.org/show_bug.cgi?id=15635
3695  */
3696  dbus_connection_ref (connection);
3697  dstatus = dbus_connection_get_dispatch_status (connection);
3698 
3699  if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
3700  {
3701  _dbus_verbose ("doing dispatch\n");
3702  dbus_connection_dispatch (connection);
3703  CONNECTION_LOCK (connection);
3704  }
3705  else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
3706  {
3707  _dbus_verbose ("pausing for memory\n");
3708  _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
3709  CONNECTION_LOCK (connection);
3710  }
3711  else
3712  {
3713  CONNECTION_LOCK (connection);
3714  if (_dbus_connection_get_is_connected_unlocked (connection))
3715  {
3716  _dbus_verbose ("doing iteration\n");
3718  NULL,
3719  DBUS_ITERATION_DO_READING |
3720  DBUS_ITERATION_DO_WRITING |
3721  DBUS_ITERATION_BLOCK,
3722  timeout_milliseconds);
3723  }
3724  }
3725 
3726  HAVE_LOCK_CHECK (connection);
3727  /* If we can dispatch, we can make progress until the Disconnected message
3728  * has been processed; if we can only read/write, we can make progress
3729  * as long as the transport is open.
3730  */
3731  if (dispatch)
3732  progress_possible = connection->n_incoming != 0 ||
3733  connection->disconnect_message_link != NULL;
3734  else
3735  progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
3736 
3737  CONNECTION_UNLOCK (connection);
3738 
3739  dbus_connection_unref (connection);
3740 
3741  return progress_possible; /* TRUE if we can make more progress */
3742 }
3743 
3744 
3781  int timeout_milliseconds)
3782 {
3783  _dbus_return_val_if_fail (connection != NULL, FALSE);
3784  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3785  return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
3786 }
3787 
3811 dbus_bool_t
3813  int timeout_milliseconds)
3814 {
3815  _dbus_return_val_if_fail (connection != NULL, FALSE);
3816  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3817  return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
3818 }
3819 
3820 /* We need to call this anytime we pop the head of the queue, and then
3821  * update_dispatch_status_and_unlock needs to be called afterward
3822  * which will "process" the disconnected message and set
3823  * disconnected_message_processed.
3824  */
3825 static void
3826 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
3827  DBusMessage *head_of_queue)
3828 {
3829  HAVE_LOCK_CHECK (connection);
3830 
3831  /* checking that the link is NULL is an optimization to avoid the is_signal call */
3832  if (connection->disconnect_message_link == NULL &&
3833  dbus_message_is_signal (head_of_queue,
3835  "Disconnected"))
3836  {
3837  connection->disconnected_message_arrived = TRUE;
3838  }
3839 }
3840 
3860 DBusMessage*
3862 {
3863  DBusDispatchStatus status;
3864  DBusMessage *message;
3865 
3866  _dbus_return_val_if_fail (connection != NULL, NULL);
3867 
3868  _dbus_verbose ("start\n");
3869 
3870  /* this is called for the side effect that it queues
3871  * up any messages from the transport
3872  */
3873  status = dbus_connection_get_dispatch_status (connection);
3874  if (status != DBUS_DISPATCH_DATA_REMAINS)
3875  return NULL;
3876 
3877  CONNECTION_LOCK (connection);
3878 
3879  _dbus_connection_acquire_dispatch (connection);
3880 
3881  /* While a message is outstanding, the dispatch lock is held */
3882  _dbus_assert (connection->message_borrowed == NULL);
3883 
3884  connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
3885 
3886  message = connection->message_borrowed;
3887 
3888  check_disconnected_message_arrived_unlocked (connection, message);
3889 
3890  /* Note that we KEEP the dispatch lock until the message is returned */
3891  if (message == NULL)
3892  _dbus_connection_release_dispatch (connection);
3893 
3894  CONNECTION_UNLOCK (connection);
3895 
3896  _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
3897 
3898  /* We don't update dispatch status until it's returned or stolen */
3899 
3900  return message;
3901 }
3902 
3911 void
3913  DBusMessage *message)
3914 {
3915  DBusDispatchStatus status;
3916 
3917  _dbus_return_if_fail (connection != NULL);
3918  _dbus_return_if_fail (message != NULL);
3919  _dbus_return_if_fail (message == connection->message_borrowed);
3920  _dbus_return_if_fail (connection->dispatch_acquired);
3921 
3922  CONNECTION_LOCK (connection);
3923 
3924  _dbus_assert (message == connection->message_borrowed);
3925 
3926  connection->message_borrowed = NULL;
3927 
3928  _dbus_connection_release_dispatch (connection);
3929 
3930  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3931  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3932 
3933  _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
3934 }
3935 
3945 void
3947  DBusMessage *message)
3948 {
3949  DBusMessage *pop_message;
3950  DBusDispatchStatus status;
3951 
3952  _dbus_return_if_fail (connection != NULL);
3953  _dbus_return_if_fail (message != NULL);
3954  _dbus_return_if_fail (message == connection->message_borrowed);
3955  _dbus_return_if_fail (connection->dispatch_acquired);
3956 
3957  CONNECTION_LOCK (connection);
3958 
3959  _dbus_assert (message == connection->message_borrowed);
3960 
3961  pop_message = _dbus_list_pop_first (&connection->incoming_messages);
3962  _dbus_assert (message == pop_message);
3963  (void) pop_message; /* unused unless asserting */
3964 
3965  connection->n_incoming -= 1;
3966 
3967  _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
3968  message, connection->n_incoming);
3969 
3970  connection->message_borrowed = NULL;
3971 
3972  _dbus_connection_release_dispatch (connection);
3973 
3974  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3975  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3976  _dbus_message_trace_ref (message, -1, -1,
3977  "dbus_connection_steal_borrowed_message");
3978 }
3979 
3980 /* See dbus_connection_pop_message, but requires the caller to own
3981  * the lock before calling. May drop the lock while running.
3982  */
3983 static DBusList*
3984 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
3985 {
3986  HAVE_LOCK_CHECK (connection);
3987 
3988  _dbus_assert (connection->message_borrowed == NULL);
3989 
3990  if (connection->n_incoming > 0)
3991  {
3992  DBusList *link;
3993 
3994  link = _dbus_list_pop_first_link (&connection->incoming_messages);
3995  connection->n_incoming -= 1;
3996 
3997  _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
3998  link->data,
4000  dbus_message_get_path (link->data) ?
4001  dbus_message_get_path (link->data) :
4002  "no path",
4005  "no interface",
4006  dbus_message_get_member (link->data) ?
4007  dbus_message_get_member (link->data) :
4008  "no member",
4010  dbus_message_get_serial (link->data),
4011  connection, connection->n_incoming);
4012 
4013  _dbus_message_trace_ref (link->data, -1, -1,
4014  "_dbus_connection_pop_message_link_unlocked");
4015 
4016  check_disconnected_message_arrived_unlocked (connection, link->data);
4017 
4018  return link;
4019  }
4020  else
4021  return NULL;
4022 }
4023 
4024 /* See dbus_connection_pop_message, but requires the caller to own
4025  * the lock before calling. May drop the lock while running.
4026  */
4027 static DBusMessage*
4028 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
4029 {
4030  DBusList *link;
4031 
4032  HAVE_LOCK_CHECK (connection);
4033 
4034  link = _dbus_connection_pop_message_link_unlocked (connection);
4035 
4036  if (link != NULL)
4037  {
4038  DBusMessage *message;
4039 
4040  message = link->data;
4041 
4042  _dbus_list_free_link (link);
4043 
4044  return message;
4045  }
4046  else
4047  return NULL;
4048 }
4049 
4050 static void
4051 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
4052  DBusList *message_link)
4053 {
4054  HAVE_LOCK_CHECK (connection);
4055 
4056  _dbus_assert (message_link != NULL);
4057  /* You can't borrow a message while a link is outstanding */
4058  _dbus_assert (connection->message_borrowed == NULL);
4059  /* We had to have the dispatch lock across the pop/putback */
4060  _dbus_assert (connection->dispatch_acquired);
4061 
4063  message_link);
4064  connection->n_incoming += 1;
4065 
4066  _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
4067  message_link->data,
4069  dbus_message_get_interface (message_link->data) ?
4070  dbus_message_get_interface (message_link->data) :
4071  "no interface",
4072  dbus_message_get_member (message_link->data) ?
4073  dbus_message_get_member (message_link->data) :
4074  "no member",
4075  dbus_message_get_signature (message_link->data),
4076  connection, connection->n_incoming);
4077 
4078  _dbus_message_trace_ref (message_link->data, -1, -1,
4079  "_dbus_connection_putback_message_link_unlocked");
4080 }
4081 
4101 DBusMessage*
4103 {
4104  DBusMessage *message;
4105  DBusDispatchStatus status;
4106 
4107  _dbus_verbose ("start\n");
4108 
4109  /* this is called for the side effect that it queues
4110  * up any messages from the transport
4111  */
4112  status = dbus_connection_get_dispatch_status (connection);
4113  if (status != DBUS_DISPATCH_DATA_REMAINS)
4114  return NULL;
4115 
4116  CONNECTION_LOCK (connection);
4117  _dbus_connection_acquire_dispatch (connection);
4118  HAVE_LOCK_CHECK (connection);
4119 
4120  message = _dbus_connection_pop_message_unlocked (connection);
4121 
4122  _dbus_verbose ("Returning popped message %p\n", message);
4123 
4124  _dbus_connection_release_dispatch (connection);
4125 
4126  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4127  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4128 
4129  return message;
4130 }
4131 
4139 static void
4140 _dbus_connection_acquire_dispatch (DBusConnection *connection)
4141 {
4142  HAVE_LOCK_CHECK (connection);
4143 
4144  _dbus_connection_ref_unlocked (connection);
4145  CONNECTION_UNLOCK (connection);
4146 
4147  _dbus_verbose ("locking dispatch_mutex\n");
4148  _dbus_cmutex_lock (connection->dispatch_mutex);
4149 
4150  while (connection->dispatch_acquired)
4151  {
4152  _dbus_verbose ("waiting for dispatch to be acquirable\n");
4153  _dbus_condvar_wait (connection->dispatch_cond,
4154  connection->dispatch_mutex);
4155  }
4156 
4157  _dbus_assert (!connection->dispatch_acquired);
4158 
4159  connection->dispatch_acquired = TRUE;
4160 
4161  _dbus_verbose ("unlocking dispatch_mutex\n");
4162  _dbus_cmutex_unlock (connection->dispatch_mutex);
4163 
4164  CONNECTION_LOCK (connection);
4165  _dbus_connection_unref_unlocked (connection);
4166 }
4167 
4175 static void
4176 _dbus_connection_release_dispatch (DBusConnection *connection)
4177 {
4178  HAVE_LOCK_CHECK (connection);
4179 
4180  _dbus_verbose ("locking dispatch_mutex\n");
4181  _dbus_cmutex_lock (connection->dispatch_mutex);
4182 
4183  _dbus_assert (connection->dispatch_acquired);
4184 
4185  connection->dispatch_acquired = FALSE;
4186  _dbus_condvar_wake_one (connection->dispatch_cond);
4187 
4188  _dbus_verbose ("unlocking dispatch_mutex\n");
4189  _dbus_cmutex_unlock (connection->dispatch_mutex);
4190 }
4191 
4192 static void
4193 _dbus_connection_failed_pop (DBusConnection *connection,
4194  DBusList *message_link)
4195 {
4197  message_link);
4198  connection->n_incoming += 1;
4199 }
4200 
4201 /* Note this may be called multiple times since we don't track whether we already did it */
4202 static void
4203 notify_disconnected_unlocked (DBusConnection *connection)
4204 {
4205  HAVE_LOCK_CHECK (connection);
4206 
4207  /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
4208  * connection from dbus_bus_get(). We make the same guarantee for
4209  * dbus_connection_open() but in a different way since we don't want to
4210  * unref right here; we instead check for connectedness before returning
4211  * the connection from the hash.
4212  */
4214 
4215  /* Dump the outgoing queue, we aren't going to be able to
4216  * send it now, and we'd like accessors like
4217  * dbus_connection_get_outgoing_size() to be accurate.
4218  */
4219  if (connection->n_outgoing > 0)
4220  {
4221  DBusList *link;
4222 
4223  _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
4224  connection->n_outgoing);
4225 
4226  while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
4227  {
4228  _dbus_connection_message_sent_unlocked (connection, link->data);
4229  }
4230  }
4231 }
4232 
4233 /* Note this may be called multiple times since we don't track whether we already did it */
4234 static DBusDispatchStatus
4235 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
4236 {
4237  HAVE_LOCK_CHECK (connection);
4238 
4239  if (connection->disconnect_message_link != NULL)
4240  {
4241  _dbus_verbose ("Sending disconnect message\n");
4242 
4243  /* If we have pending calls, queue their timeouts - we want the Disconnected
4244  * to be the last message, after these timeouts.
4245  */
4246  connection_timeout_and_complete_all_pending_calls_unlocked (connection);
4247 
4248  /* We haven't sent the disconnect message already,
4249  * and all real messages have been queued up.
4250  */
4252  connection->disconnect_message_link);
4253  connection->disconnect_message_link = NULL;
4254 
4256  }
4257 
4258  return DBUS_DISPATCH_COMPLETE;
4259 }
4260 
4261 static DBusDispatchStatus
4262 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
4263 {
4264  HAVE_LOCK_CHECK (connection);
4265 
4266  if (connection->n_incoming > 0)
4268  else if (!_dbus_transport_queue_messages (connection->transport))
4270  else
4271  {
4272  DBusDispatchStatus status;
4273  dbus_bool_t is_connected;
4274 
4275  status = _dbus_transport_get_dispatch_status (connection->transport);
4276  is_connected = _dbus_transport_get_is_connected (connection->transport);
4277 
4278  _dbus_verbose ("dispatch status = %s is_connected = %d\n",
4279  DISPATCH_STATUS_NAME (status), is_connected);
4280 
4281  if (!is_connected)
4282  {
4283  /* It's possible this would be better done by having an explicit
4284  * notification from _dbus_transport_disconnect() that would
4285  * synchronously do this, instead of waiting for the next dispatch
4286  * status check. However, probably not good to change until it causes
4287  * a problem.
4288  */
4289  notify_disconnected_unlocked (connection);
4290 
4291  /* I'm not sure this is needed; the idea is that we want to
4292  * queue the Disconnected only after we've read all the
4293  * messages, but if we're disconnected maybe we are guaranteed
4294  * to have read them all ?
4295  */
4296  if (status == DBUS_DISPATCH_COMPLETE)
4297  status = notify_disconnected_and_dispatch_complete_unlocked (connection);
4298  }
4299 
4300  if (status != DBUS_DISPATCH_COMPLETE)
4301  return status;
4302  else if (connection->n_incoming > 0)
4304  else
4305  return DBUS_DISPATCH_COMPLETE;
4306  }
4307 }
4308 
4309 static void
4310 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
4311  DBusDispatchStatus new_status)
4312 {
4313  dbus_bool_t changed;
4314  DBusDispatchStatusFunction function;
4315  void *data;
4316 
4317  HAVE_LOCK_CHECK (connection);
4318 
4319  _dbus_connection_ref_unlocked (connection);
4320 
4321  changed = new_status != connection->last_dispatch_status;
4322 
4323  connection->last_dispatch_status = new_status;
4324 
4325  function = connection->dispatch_status_function;
4326  data = connection->dispatch_status_data;
4327 
4328  if (connection->disconnected_message_arrived &&
4329  !connection->disconnected_message_processed)
4330  {
4331  connection->disconnected_message_processed = TRUE;
4332 
4333  /* this does an unref, but we have a ref
4334  * so we should not run the finalizer here
4335  * inside the lock.
4336  */
4337  connection_forget_shared_unlocked (connection);
4338 
4339  if (connection->exit_on_disconnect)
4340  {
4341  CONNECTION_UNLOCK (connection);
4342 
4343  _dbus_verbose ("Exiting on Disconnected signal\n");
4344  _dbus_exit (1);
4345  _dbus_assert_not_reached ("Call to exit() returned");
4346  }
4347  }
4348 
4349  /* We drop the lock */
4350  CONNECTION_UNLOCK (connection);
4351 
4352  if (changed && function)
4353  {
4354  _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
4355  connection, new_status,
4356  DISPATCH_STATUS_NAME (new_status));
4357  (* function) (connection, new_status, data);
4358  }
4359 
4360  dbus_connection_unref (connection);
4361 }
4362 
4390 {
4391  DBusDispatchStatus status;
4392 
4393  _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4394 
4395  _dbus_verbose ("start\n");
4396 
4397  CONNECTION_LOCK (connection);
4398 
4399  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4400 
4401  CONNECTION_UNLOCK (connection);
4402 
4403  return status;
4404 }
4405 
4409 static DBusHandlerResult
4410 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
4411  DBusMessage *message)
4412 {
4413  dbus_bool_t sent = FALSE;
4414  DBusMessage *ret = NULL;
4415  DBusList *expire_link;
4416 
4417  if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
4418  {
4419  /* This means we're letting the bus route this message */
4421  }
4422 
4424  {
4426  }
4427 
4428  /* Preallocate a linked-list link, so that if we need to dispose of a
4429  * message, we can attach it to the expired list */
4430  expire_link = _dbus_list_alloc_link (NULL);
4431 
4432  if (!expire_link)
4434 
4435  if (dbus_message_is_method_call (message,
4437  "Ping"))
4438  {
4439  ret = dbus_message_new_method_return (message);
4440  if (ret == NULL)
4441  goto out;
4442 
4443  sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4444  }
4445  else if (dbus_message_is_method_call (message,
4447  "GetMachineId"))
4448  {
4449  DBusString uuid;
4450  DBusError error = DBUS_ERROR_INIT;
4451 
4452  if (!_dbus_string_init (&uuid))
4453  goto out;
4454 
4455  if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
4456  {
4457  const char *v_STRING;
4458 
4459  ret = dbus_message_new_method_return (message);
4460 
4461  if (ret == NULL)
4462  {
4463  _dbus_string_free (&uuid);
4464  goto out;
4465  }
4466 
4467  v_STRING = _dbus_string_get_const_data (&uuid);
4468  if (dbus_message_append_args (ret,
4469  DBUS_TYPE_STRING, &v_STRING,
4471  {
4472  sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4473  }
4474  }
4475  else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
4476  {
4477  dbus_error_free (&error);
4478  goto out;
4479  }
4480  else
4481  {
4482  ret = dbus_message_new_error (message, error.name, error.message);
4483  dbus_error_free (&error);
4484 
4485  if (ret == NULL)
4486  goto out;
4487 
4488  sent = _dbus_connection_send_unlocked_no_update (connection, ret,
4489  NULL);
4490  }
4491 
4492  _dbus_string_free (&uuid);
4493  }
4494  else
4495  {
4496  /* We need to bounce anything else with this interface, otherwise apps
4497  * could start extending the interface and when we added extensions
4498  * here to DBusConnection we'd break those apps.
4499  */
4500  ret = dbus_message_new_error (message,
4502  "Unknown method invoked on org.freedesktop.DBus.Peer interface");
4503  if (ret == NULL)
4504  goto out;
4505 
4506  sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4507  }
4508 
4509 out:
4510  if (ret == NULL)
4511  {
4512  _dbus_list_free_link (expire_link);
4513  }
4514  else
4515  {
4516  /* It'll be safe to unref the reply when we unlock */
4517  expire_link->data = ret;
4518  _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4519  }
4520 
4521  if (!sent)
4523 
4525 }
4526 
4533 static DBusHandlerResult
4534 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
4535  DBusMessage *message)
4536 {
4537  /* We just run one filter for now but have the option to run more
4538  if the spec calls for it in the future */
4539 
4540  return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
4541 }
4542 
4587 {
4588  DBusMessage *message;
4589  DBusList *link, *filter_list_copy, *message_link;
4590  DBusHandlerResult result;
4591  DBusPendingCall *pending;
4592  dbus_int32_t reply_serial;
4593  DBusDispatchStatus status;
4594  dbus_bool_t found_object;
4595 
4596  _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4597 
4598  _dbus_verbose ("\n");
4599 
4600  CONNECTION_LOCK (connection);
4601  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4602  if (status != DBUS_DISPATCH_DATA_REMAINS)
4603  {
4604  /* unlocks and calls out to user code */
4605  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4606  return status;
4607  }
4608 
4609  /* We need to ref the connection since the callback could potentially
4610  * drop the last ref to it
4611  */
4612  _dbus_connection_ref_unlocked (connection);
4613 
4614  _dbus_connection_acquire_dispatch (connection);
4615  HAVE_LOCK_CHECK (connection);
4616 
4617  message_link = _dbus_connection_pop_message_link_unlocked (connection);
4618  if (message_link == NULL)
4619  {
4620  /* another thread dispatched our stuff */
4621 
4622  _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
4623 
4624  _dbus_connection_release_dispatch (connection);
4625 
4626  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4627 
4628  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4629 
4630  dbus_connection_unref (connection);
4631 
4632  return status;
4633  }
4634 
4635  message = message_link->data;
4636 
4637  _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
4638  message,
4640  dbus_message_get_interface (message) ?
4641  dbus_message_get_interface (message) :
4642  "no interface",
4643  dbus_message_get_member (message) ?
4644  dbus_message_get_member (message) :
4645  "no member",
4646  dbus_message_get_signature (message));
4647 
4649 
4650  /* Pending call handling must be first, because if you do
4651  * dbus_connection_send_with_reply_and_block() or
4652  * dbus_pending_call_block() then no handlers/filters will be run on
4653  * the reply. We want consistent semantics in the case where we
4654  * dbus_connection_dispatch() the reply.
4655  */
4656 
4657  reply_serial = dbus_message_get_reply_serial (message);
4658  pending = _dbus_hash_table_lookup_int (connection->pending_replies,
4659  reply_serial);
4660  if (pending)
4661  {
4662  _dbus_verbose ("Dispatching a pending reply\n");
4663  complete_pending_call_and_unlock (connection, pending, message);
4664  pending = NULL; /* it's probably unref'd */
4665 
4666  CONNECTION_LOCK (connection);
4667  _dbus_verbose ("pending call completed in dispatch\n");
4668  result = DBUS_HANDLER_RESULT_HANDLED;
4669  goto out;
4670  }
4671 
4672  /* If skipping builtin filters, we are probably a monitor. */
4673  if (connection->builtin_filters_enabled)
4674  {
4675  result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
4677  goto out;
4678  }
4679 
4680  if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
4681  {
4682  _dbus_connection_release_dispatch (connection);
4683  HAVE_LOCK_CHECK (connection);
4684 
4685  _dbus_connection_failed_pop (connection, message_link);
4686 
4687  /* unlocks and calls user code */
4688  _dbus_connection_update_dispatch_status_and_unlock (connection,
4690  dbus_connection_unref (connection);
4691 
4693  }
4694 
4695  for (link = _dbus_list_get_first_link (&filter_list_copy);
4696  link != NULL;
4697  link = _dbus_list_get_next_link (&filter_list_copy, link))
4698  _dbus_message_filter_ref (link->data);
4699 
4700  /* We're still protected from dispatch() reentrancy here
4701  * since we acquired the dispatcher
4702  */
4703  CONNECTION_UNLOCK (connection);
4704 
4705  link = _dbus_list_get_first_link (&filter_list_copy);
4706  while (link != NULL)
4707  {
4708  DBusMessageFilter *filter = link->data;
4709  DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
4710 
4711  if (filter->function == NULL)
4712  {
4713  _dbus_verbose (" filter was removed in a callback function\n");
4714  link = next;
4715  continue;
4716  }
4717 
4718  _dbus_verbose (" running filter on message %p\n", message);
4719  result = (* filter->function) (connection, message, filter->user_data);
4720 
4722  break;
4723 
4724  link = next;
4725  }
4726 
4727  _dbus_list_clear_full (&filter_list_copy,
4728  (DBusFreeFunction) _dbus_message_filter_unref);
4729 
4730  CONNECTION_LOCK (connection);
4731 
4732  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4733  {
4734  _dbus_verbose ("No memory\n");
4735  goto out;
4736  }
4737  else if (result == DBUS_HANDLER_RESULT_HANDLED)
4738  {
4739  _dbus_verbose ("filter handled message in dispatch\n");
4740  goto out;
4741  }
4742 
4743  /* We're still protected from dispatch() reentrancy here
4744  * since we acquired the dispatcher
4745  */
4746  _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
4747  message,
4749  dbus_message_get_interface (message) ?
4750  dbus_message_get_interface (message) :
4751  "no interface",
4752  dbus_message_get_member (message) ?
4753  dbus_message_get_member (message) :
4754  "no member",
4755  dbus_message_get_signature (message));
4756 
4757  HAVE_LOCK_CHECK (connection);
4758  result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
4759  message,
4760  &found_object);
4761 
4762  CONNECTION_LOCK (connection);
4763 
4765  {
4766  _dbus_verbose ("object tree handled message in dispatch\n");
4767  goto out;
4768  }
4769 
4771  {
4772  DBusMessage *reply;
4773  DBusString str;
4774  DBusPreallocatedSend *preallocated;
4775  DBusList *expire_link;
4776 
4777  _dbus_verbose (" sending error %s\n",
4779 
4780  if (!_dbus_string_init (&str))
4781  {
4783  _dbus_verbose ("no memory for error string in dispatch\n");
4784  goto out;
4785  }
4786 
4787  if (!_dbus_string_append_printf (&str,
4788  "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
4789  dbus_message_get_member (message),
4790  dbus_message_get_signature (message),
4791  dbus_message_get_interface (message)))
4792  {
4793  _dbus_string_free (&str);
4795  _dbus_verbose ("no memory for error string in dispatch\n");
4796  goto out;
4797  }
4798 
4799  reply = dbus_message_new_error (message,
4801  _dbus_string_get_const_data (&str));
4802  _dbus_string_free (&str);
4803 
4804  if (reply == NULL)
4805  {
4807  _dbus_verbose ("no memory for error reply in dispatch\n");
4808  goto out;
4809  }
4810 
4811  expire_link = _dbus_list_alloc_link (reply);
4812 
4813  if (expire_link == NULL)
4814  {
4815  dbus_message_unref (reply);
4817  _dbus_verbose ("no memory for error send in dispatch\n");
4818  goto out;
4819  }
4820 
4821  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
4822 
4823  if (preallocated == NULL)
4824  {
4825  _dbus_list_free_link (expire_link);
4826  /* It's OK that this is finalized, because it hasn't been seen by
4827  * anything that could attach user callbacks */
4828  dbus_message_unref (reply);
4830  _dbus_verbose ("no memory for error send in dispatch\n");
4831  goto out;
4832  }
4833 
4834  _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
4835  reply, NULL);
4836  /* reply will be freed when we release the lock */
4837  _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4838 
4839  result = DBUS_HANDLER_RESULT_HANDLED;
4840  }
4841 
4842  _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
4844  dbus_message_get_interface (message) ?
4845  dbus_message_get_interface (message) :
4846  "no interface",
4847  dbus_message_get_member (message) ?
4848  dbus_message_get_member (message) :
4849  "no member",
4850  dbus_message_get_signature (message),
4851  connection);
4852 
4853  out:
4854  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4855  {
4856  _dbus_verbose ("out of memory\n");
4857 
4858  /* Put message back, and we'll start over.
4859  * Yes this means handlers must be idempotent if they
4860  * don't return HANDLED; c'est la vie.
4861  */
4862  _dbus_connection_putback_message_link_unlocked (connection,
4863  message_link);
4864  /* now we don't want to free them */
4865  message_link = NULL;
4866  message = NULL;
4867  }
4868  else
4869  {
4870  _dbus_verbose (" ... done dispatching\n");
4871  }
4872 
4873  _dbus_connection_release_dispatch (connection);
4874  HAVE_LOCK_CHECK (connection);
4875 
4876  if (message != NULL)
4877  {
4878  /* We don't want this message to count in maximum message limits when
4879  * computing the dispatch status, below. We have to drop the lock
4880  * temporarily, because finalizing a message can trigger callbacks.
4881  *
4882  * We have a reference to the connection, and we don't use any cached
4883  * pointers to the connection's internals below this point, so it should
4884  * be safe to drop the lock and take it back. */
4885  CONNECTION_UNLOCK (connection);
4886  dbus_message_unref (message);
4887  CONNECTION_LOCK (connection);
4888  }
4889 
4890  if (message_link != NULL)
4891  _dbus_list_free_link (message_link);
4892 
4893  _dbus_verbose ("before final status update\n");
4894  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4895 
4896  /* unlocks and calls user code */
4897  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4898 
4899  dbus_connection_unref (connection);
4900 
4901  return status;
4902 }
4903 
4967  DBusAddWatchFunction add_function,
4968  DBusRemoveWatchFunction remove_function,
4969  DBusWatchToggledFunction toggled_function,
4970  void *data,
4971  DBusFreeFunction free_data_function)
4972 {
4973  dbus_bool_t retval;
4974 
4975  _dbus_return_val_if_fail (connection != NULL, FALSE);
4976 
4977  CONNECTION_LOCK (connection);
4978 
4979  retval = _dbus_watch_list_set_functions (connection->watches,
4980  add_function, remove_function,
4981  toggled_function,
4982  data, free_data_function);
4983 
4984  CONNECTION_UNLOCK (connection);
4985 
4986  return retval;
4987 }
4988 
5030  DBusAddTimeoutFunction add_function,
5031  DBusRemoveTimeoutFunction remove_function,
5032  DBusTimeoutToggledFunction toggled_function,
5033  void *data,
5034  DBusFreeFunction free_data_function)
5035 {
5036  dbus_bool_t retval;
5037 
5038  _dbus_return_val_if_fail (connection != NULL, FALSE);
5039 
5040  CONNECTION_LOCK (connection);
5041 
5042  retval = _dbus_timeout_list_set_functions (connection->timeouts,
5043  add_function, remove_function,
5044  toggled_function,
5045  data, free_data_function);
5046 
5047  CONNECTION_UNLOCK (connection);
5048 
5049  return retval;
5050 }
5051 
5066 void
5068  DBusWakeupMainFunction wakeup_main_function,
5069  void *data,
5070  DBusFreeFunction free_data_function)
5071 {
5072  void *old_data;
5073  DBusFreeFunction old_free_data;
5074 
5075  _dbus_return_if_fail (connection != NULL);
5076 
5077  CONNECTION_LOCK (connection);
5078  old_data = connection->wakeup_main_data;
5079  old_free_data = connection->free_wakeup_main_data;
5080 
5081  connection->wakeup_main_function = wakeup_main_function;
5082  connection->wakeup_main_data = data;
5083  connection->free_wakeup_main_data = free_data_function;
5084 
5085  CONNECTION_UNLOCK (connection);
5086 
5087  /* Callback outside the lock */
5088  if (old_free_data)
5089  (*old_free_data) (old_data);
5090 }
5091 
5112 void
5114  DBusDispatchStatusFunction function,
5115  void *data,
5116  DBusFreeFunction free_data_function)
5117 {
5118  void *old_data;
5119  DBusFreeFunction old_free_data;
5120 
5121  _dbus_return_if_fail (connection != NULL);
5122 
5123  CONNECTION_LOCK (connection);
5124  old_data = connection->dispatch_status_data;
5125  old_free_data = connection->free_dispatch_status_data;
5126 
5127  connection->dispatch_status_function = function;
5128  connection->dispatch_status_data = data;
5129  connection->free_dispatch_status_data = free_data_function;
5130 
5131  CONNECTION_UNLOCK (connection);
5132 
5133  /* Callback outside the lock */
5134  if (old_free_data)
5135  (*old_free_data) (old_data);
5136 }
5137 
5159  int *fd)
5160 {
5161  _dbus_return_val_if_fail (connection != NULL, FALSE);
5162  _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5163 
5164 #ifdef DBUS_WIN
5165  /* FIXME do this on a lower level */
5166  return FALSE;
5167 #endif
5168 
5169  return dbus_connection_get_socket(connection, fd);
5170 }
5171 
5189  int *fd)
5190 {
5191  dbus_bool_t retval;
5192  DBusSocket s = DBUS_SOCKET_INIT;
5193 
5194  _dbus_return_val_if_fail (connection != NULL, FALSE);
5195  _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5196 
5197  CONNECTION_LOCK (connection);
5198 
5199  retval = _dbus_transport_get_socket_fd (connection->transport, &s);
5200 
5201  if (retval)
5202  {
5203  *fd = _dbus_socket_get_int (s);
5204  }
5205 
5206  CONNECTION_UNLOCK (connection);
5207 
5208  return retval;
5209 }
5210 
5211 
5236  unsigned long *uid)
5237 {
5238  dbus_bool_t result;
5239 
5240  _dbus_return_val_if_fail (connection != NULL, FALSE);
5241  _dbus_return_val_if_fail (uid != NULL, FALSE);
5242 
5243  CONNECTION_LOCK (connection);
5244 
5246  result = FALSE;
5247  else
5248  result = _dbus_transport_get_unix_user (connection->transport,
5249  uid);
5250 
5251 #ifdef DBUS_WIN
5252  _dbus_assert (!result);
5253 #endif
5254 
5255  CONNECTION_UNLOCK (connection);
5256 
5257  return result;
5258 }
5259 
5272  unsigned long *pid)
5273 {
5274  dbus_bool_t result;
5275 
5276  _dbus_return_val_if_fail (connection != NULL, FALSE);
5277  _dbus_return_val_if_fail (pid != NULL, FALSE);
5278 
5279  CONNECTION_LOCK (connection);
5280 
5282  result = FALSE;
5283  else
5284  result = _dbus_transport_get_unix_process_id (connection->transport,
5285  pid);
5286 
5287  CONNECTION_UNLOCK (connection);
5288 
5289  return result;
5290 }
5291 
5305  void **data,
5306  dbus_int32_t *data_size)
5307 {
5308  dbus_bool_t result;
5309 
5310  _dbus_return_val_if_fail (connection != NULL, FALSE);
5311  _dbus_return_val_if_fail (data != NULL, FALSE);
5312  _dbus_return_val_if_fail (data_size != NULL, FALSE);
5313 
5314  CONNECTION_LOCK (connection);
5315 
5317  result = FALSE;
5318  else
5320  data,
5321  data_size);
5322  CONNECTION_UNLOCK (connection);
5323 
5324  return result;
5325 }
5326 
5349 void
5351  DBusAllowUnixUserFunction function,
5352  void *data,
5353  DBusFreeFunction free_data_function)
5354 {
5355  void *old_data = NULL;
5356  DBusFreeFunction old_free_function = NULL;
5357 
5358  _dbus_return_if_fail (connection != NULL);
5359 
5360  CONNECTION_LOCK (connection);
5362  function, data, free_data_function,
5363  &old_data, &old_free_function);
5364  CONNECTION_UNLOCK (connection);
5365 
5366  if (old_free_function != NULL)
5367  (* old_free_function) (old_data);
5368 }
5369 
5370 /* Same calling convention as dbus_connection_get_windows_user */
5372 _dbus_connection_get_linux_security_label (DBusConnection *connection,
5373  char **label_p)
5374 {
5375  dbus_bool_t result;
5376 
5377  _dbus_assert (connection != NULL);
5378  _dbus_assert (label_p != NULL);
5379 
5380  CONNECTION_LOCK (connection);
5381 
5383  result = FALSE;
5384  else
5385  result = _dbus_transport_get_linux_security_label (connection->transport,
5386  label_p);
5387 #ifndef __linux__
5388  _dbus_assert (!result);
5389 #endif
5390 
5391  CONNECTION_UNLOCK (connection);
5392 
5393  return result;
5394 }
5395 
5397 _dbus_connection_get_credentials (DBusConnection *connection)
5398 {
5399  DBusCredentials *result;
5400 
5401  _dbus_assert (connection != NULL);
5402 
5403  CONNECTION_LOCK (connection);
5404 
5406  result = NULL;
5407  else
5408  result = _dbus_transport_get_credentials (connection->transport);
5409 
5410  CONNECTION_UNLOCK (connection);
5411 
5412  return result;
5413 }
5414 
5448  char **windows_sid_p)
5449 {
5450  dbus_bool_t result;
5451 
5452  _dbus_return_val_if_fail (connection != NULL, FALSE);
5453  _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
5454 
5455  CONNECTION_LOCK (connection);
5456 
5458  result = FALSE;
5459  else
5460  result = _dbus_transport_get_windows_user (connection->transport,
5461  windows_sid_p);
5462 
5463 #ifdef DBUS_UNIX
5464  _dbus_assert (!result);
5465 #endif
5466 
5467  CONNECTION_UNLOCK (connection);
5468 
5469  return result;
5470 }
5471 
5493 void
5496  void *data,
5497  DBusFreeFunction free_data_function)
5498 {
5499  void *old_data = NULL;
5500  DBusFreeFunction old_free_function = NULL;
5501 
5502  _dbus_return_if_fail (connection != NULL);
5503 
5504  CONNECTION_LOCK (connection);
5506  function, data, free_data_function,
5507  &old_data, &old_free_function);
5508  CONNECTION_UNLOCK (connection);
5509 
5510  if (old_free_function != NULL)
5511  (* old_free_function) (old_data);
5512 }
5513 
5540 void
5542  dbus_bool_t value)
5543 {
5544  _dbus_return_if_fail (connection != NULL);
5545 
5546  CONNECTION_LOCK (connection);
5547  _dbus_transport_set_allow_anonymous (connection->transport, value);
5548  CONNECTION_UNLOCK (connection);
5549 }
5550 
5572 void
5574  dbus_bool_t value)
5575 {
5576  _dbus_assert (connection != NULL);
5577 
5578  CONNECTION_LOCK (connection);
5579  connection->builtin_filters_enabled = value;
5580  CONNECTION_UNLOCK (connection);
5581 }
5582 
5600 void
5602  dbus_bool_t value)
5603 {
5604  _dbus_return_if_fail (connection != NULL);
5605 
5606  CONNECTION_LOCK (connection);
5607  connection->route_peer_messages = value;
5608  CONNECTION_UNLOCK (connection);
5609 }
5610 
5634  DBusHandleMessageFunction function,
5635  void *user_data,
5636  DBusFreeFunction free_data_function)
5637 {
5638  DBusMessageFilter *filter;
5639 
5640  _dbus_return_val_if_fail (connection != NULL, FALSE);
5641  _dbus_return_val_if_fail (function != NULL, FALSE);
5642 
5643  filter = dbus_new0 (DBusMessageFilter, 1);
5644  if (filter == NULL)
5645  return FALSE;
5646 
5647  _dbus_atomic_inc (&filter->refcount);
5648 
5649  CONNECTION_LOCK (connection);
5650 
5651  if (!_dbus_list_append (&connection->filter_list,
5652  filter))
5653  {
5654  _dbus_message_filter_unref (filter);
5655  CONNECTION_UNLOCK (connection);
5656  return FALSE;
5657  }
5658 
5659  /* Fill in filter after all memory allocated,
5660  * so we don't run the free_user_data_function
5661  * if the add_filter() fails
5662  */
5663 
5664  filter->function = function;
5665  filter->user_data = user_data;
5666  filter->free_user_data_function = free_data_function;
5667 
5668  CONNECTION_UNLOCK (connection);
5669  return TRUE;
5670 }
5671 
5684 void
5686  DBusHandleMessageFunction function,
5687  void *user_data)
5688 {
5689  DBusList *link;
5690  DBusMessageFilter *filter;
5691 
5692  _dbus_return_if_fail (connection != NULL);
5693  _dbus_return_if_fail (function != NULL);
5694 
5695  CONNECTION_LOCK (connection);
5696 
5697  filter = NULL;
5698 
5699  link = _dbus_list_get_last_link (&connection->filter_list);
5700  while (link != NULL)
5701  {
5702  filter = link->data;
5703 
5704  if (filter->function == function &&
5705  filter->user_data == user_data)
5706  {
5707  _dbus_list_remove_link (&connection->filter_list, link);
5708  filter->function = NULL;
5709 
5710  break;
5711  }
5712 
5713  link = _dbus_list_get_prev_link (&connection->filter_list, link);
5714  filter = NULL;
5715  }
5716 
5717  CONNECTION_UNLOCK (connection);
5718 
5719 #ifndef DBUS_DISABLE_CHECKS
5720  if (filter == NULL)
5721  {
5722  _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
5723  function, user_data);
5724  return;
5725  }
5726 #endif
5727 
5728  /* Call application code */
5729  if (filter->free_user_data_function)
5730  (* filter->free_user_data_function) (filter->user_data);
5731 
5732  filter->free_user_data_function = NULL;
5733  filter->user_data = NULL;
5734 
5735  _dbus_message_filter_unref (filter);
5736 }
5737 
5753 static dbus_bool_t
5754 _dbus_connection_register_object_path (DBusConnection *connection,
5755  dbus_bool_t fallback,
5756  const char *path,
5757  const DBusObjectPathVTable *vtable,
5758  void *user_data,
5759  DBusError *error)
5760 {
5761  char **decomposed_path;
5762  dbus_bool_t retval;
5763 
5764  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5765  return FALSE;
5766 
5767  CONNECTION_LOCK (connection);
5768 
5769  retval = _dbus_object_tree_register (connection->objects,
5770  fallback,
5771  (const char **) decomposed_path, vtable,
5772  user_data, error);
5773 
5774  CONNECTION_UNLOCK (connection);
5775 
5776  dbus_free_string_array (decomposed_path);
5777 
5778  return retval;
5779 }
5780 
5795  const char *path,
5796  const DBusObjectPathVTable *vtable,
5797  void *user_data,
5798  DBusError *error)
5799 {
5800  _dbus_return_val_if_fail (connection != NULL, FALSE);
5801  _dbus_return_val_if_fail (path != NULL, FALSE);
5802  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5803  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5804 
5805  return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
5806 }
5807 
5825  const char *path,
5826  const DBusObjectPathVTable *vtable,
5827  void *user_data)
5828 {
5829  dbus_bool_t retval;
5830  DBusError error = DBUS_ERROR_INIT;
5831 
5832  _dbus_return_val_if_fail (connection != NULL, FALSE);
5833  _dbus_return_val_if_fail (path != NULL, FALSE);
5834  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5835  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5836 
5837  retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
5838 
5840  {
5841  _dbus_warn ("%s", error.message);
5842  dbus_error_free (&error);
5843  return FALSE;
5844  }
5845 
5846  return retval;
5847 }
5848 
5865  const char *path,
5866  const DBusObjectPathVTable *vtable,
5867  void *user_data,
5868  DBusError *error)
5869 {
5870  _dbus_return_val_if_fail (connection != NULL, FALSE);
5871  _dbus_return_val_if_fail (path != NULL, FALSE);
5872  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5873  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5874 
5875  return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
5876 }
5877 
5897  const char *path,
5898  const DBusObjectPathVTable *vtable,
5899  void *user_data)
5900 {
5901  dbus_bool_t retval;
5902  DBusError error = DBUS_ERROR_INIT;
5903 
5904  _dbus_return_val_if_fail (connection != NULL, FALSE);
5905  _dbus_return_val_if_fail (path != NULL, FALSE);
5906  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5907  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5908 
5909  retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
5910 
5912  {
5913  _dbus_warn ("%s", error.message);
5914  dbus_error_free (&error);
5915  return FALSE;
5916  }
5917 
5918  return retval;
5919 }
5920 
5932  const char *path)
5933 {
5934  char **decomposed_path;
5935 
5936  _dbus_return_val_if_fail (connection != NULL, FALSE);
5937  _dbus_return_val_if_fail (path != NULL, FALSE);
5938  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5939 
5940  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5941  return FALSE;
5942 
5943  CONNECTION_LOCK (connection);
5944 
5945  _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
5946 
5947  dbus_free_string_array (decomposed_path);
5948 
5949  return TRUE;
5950 }
5951 
5964  const char *path,
5965  void **data_p)
5966 {
5967  char **decomposed_path;
5968 
5969  _dbus_return_val_if_fail (connection != NULL, FALSE);
5970  _dbus_return_val_if_fail (path != NULL, FALSE);
5971  _dbus_return_val_if_fail (data_p != NULL, FALSE);
5972 
5973  *data_p = NULL;
5974 
5975  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5976  return FALSE;
5977 
5978  CONNECTION_LOCK (connection);
5979 
5980  *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
5981 
5982  CONNECTION_UNLOCK (connection);
5983 
5984  dbus_free_string_array (decomposed_path);
5985 
5986  return TRUE;
5987 }
5988 
6001  const char *parent_path,
6002  char ***child_entries)
6003 {
6004  char **decomposed_path;
6005  dbus_bool_t retval;
6006  _dbus_return_val_if_fail (connection != NULL, FALSE);
6007  _dbus_return_val_if_fail (parent_path != NULL, FALSE);
6008  _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
6009  _dbus_return_val_if_fail (child_entries != NULL, FALSE);
6010 
6011  if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
6012  return FALSE;
6013 
6014  CONNECTION_LOCK (connection);
6015 
6017  (const char **) decomposed_path,
6018  child_entries);
6019  dbus_free_string_array (decomposed_path);
6020 
6021  return retval;
6022 }
6023 
6024 static DBusDataSlotAllocator slot_allocator =
6025  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
6026 
6043 {
6044  return _dbus_data_slot_allocator_alloc (&slot_allocator,
6045  slot_p);
6046 }
6047 
6059 void
6060 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
6061 {
6062  _dbus_return_if_fail (*slot_p >= 0);
6063 
6064  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
6065 }
6066 
6091  dbus_int32_t slot,
6092  void *data,
6093  DBusFreeFunction free_data_func)
6094 {
6095  DBusFreeFunction old_free_func;
6096  void *old_data;
6097  dbus_bool_t retval;
6098 
6099  _dbus_return_val_if_fail (connection != NULL, FALSE);
6100  _dbus_return_val_if_fail (slot >= 0, FALSE);
6101 
6102  SLOTS_LOCK (connection);
6103 
6104  retval = _dbus_data_slot_list_set (&slot_allocator,
6105  &connection->slot_list,
6106  slot, data, free_data_func,
6107  &old_free_func, &old_data);
6108 
6109  SLOTS_UNLOCK (connection);
6110 
6111  if (retval)
6112  {
6113  /* Do the actual free outside the connection lock */
6114  if (old_free_func)
6115  (* old_free_func) (old_data);
6116  }
6117 
6118  return retval;
6119 }
6120 
6138 void*
6140  dbus_int32_t slot)
6141 {
6142  void *res;
6143 
6144  _dbus_return_val_if_fail (connection != NULL, NULL);
6145  _dbus_return_val_if_fail (slot >= 0, NULL);
6146 
6147  SLOTS_LOCK (connection);
6148 
6149  res = _dbus_data_slot_list_get (&slot_allocator,
6150  &connection->slot_list,
6151  slot);
6152 
6153  SLOTS_UNLOCK (connection);
6154 
6155  return res;
6156 }
6157 
6164 void
6166 {
6167  if (will_modify_sigpipe)
6168  _dbus_atomic_set_nonzero (&_dbus_modify_sigpipe);
6169  else
6170  _dbus_atomic_set_zero (&_dbus_modify_sigpipe);
6171 }
6172 
6181 void
6183  long size)
6184 {
6185  _dbus_return_if_fail (connection != NULL);
6186 
6187  CONNECTION_LOCK (connection);
6189  size);
6190  CONNECTION_UNLOCK (connection);
6191 }
6192 
6199 long
6201 {
6202  long res;
6203 
6204  _dbus_return_val_if_fail (connection != NULL, 0);
6205 
6206  CONNECTION_LOCK (connection);
6207  res = _dbus_transport_get_max_message_size (connection->transport);
6208  CONNECTION_UNLOCK (connection);
6209  return res;
6210 }
6211 
6220 void
6222  long n)
6223 {
6224  _dbus_return_if_fail (connection != NULL);
6225 
6226  CONNECTION_LOCK (connection);
6228  n);
6229  CONNECTION_UNLOCK (connection);
6230 }
6231 
6238 long
6240 {
6241  long res;
6242 
6243  _dbus_return_val_if_fail (connection != NULL, 0);
6244 
6245  CONNECTION_LOCK (connection);
6247  CONNECTION_UNLOCK (connection);
6248  return res;
6249 }
6250 
6276 void
6278  long size)
6279 {
6280  _dbus_return_if_fail (connection != NULL);
6281 
6282  CONNECTION_LOCK (connection);
6284  size);
6285  CONNECTION_UNLOCK (connection);
6286 }
6287 
6294 long
6296 {
6297  long res;
6298 
6299  _dbus_return_val_if_fail (connection != NULL, 0);
6300 
6301  CONNECTION_LOCK (connection);
6303  CONNECTION_UNLOCK (connection);
6304  return res;
6305 }
6306 
6318 void
6320  long n)
6321 {
6322  _dbus_return_if_fail (connection != NULL);
6323 
6324  CONNECTION_LOCK (connection);
6326  n);
6327  CONNECTION_UNLOCK (connection);
6328 }
6329 
6336 long
6338 {
6339  long res;
6340 
6341  _dbus_return_val_if_fail (connection != NULL, 0);
6342 
6343  CONNECTION_LOCK (connection);
6345  CONNECTION_UNLOCK (connection);
6346  return res;
6347 }
6348 
6359 long
6361 {
6362  long res;
6363 
6364  _dbus_return_val_if_fail (connection != NULL, 0);
6365 
6366  CONNECTION_LOCK (connection);
6367  res = _dbus_counter_get_size_value (connection->outgoing_counter);
6368  CONNECTION_UNLOCK (connection);
6369  return res;
6370 }
6371 
6372 #ifdef DBUS_ENABLE_STATS
6373 void
6374 _dbus_connection_get_stats (DBusConnection *connection,
6375  dbus_uint32_t *in_messages,
6376  dbus_uint32_t *in_bytes,
6377  dbus_uint32_t *in_fds,
6378  dbus_uint32_t *in_peak_bytes,
6379  dbus_uint32_t *in_peak_fds,
6380  dbus_uint32_t *out_messages,
6381  dbus_uint32_t *out_bytes,
6382  dbus_uint32_t *out_fds,
6383  dbus_uint32_t *out_peak_bytes,
6384  dbus_uint32_t *out_peak_fds)
6385 {
6386  CONNECTION_LOCK (connection);
6387 
6388  if (in_messages != NULL)
6389  *in_messages = connection->n_incoming;
6390 
6391  _dbus_transport_get_stats (connection->transport,
6392  in_bytes, in_fds, in_peak_bytes, in_peak_fds);
6393 
6394  if (out_messages != NULL)
6395  *out_messages = connection->n_outgoing;
6396 
6397  if (out_bytes != NULL)
6398  *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
6399 
6400  if (out_fds != NULL)
6401  *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
6402 
6403  if (out_peak_bytes != NULL)
6404  *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
6405 
6406  if (out_peak_fds != NULL)
6407  *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
6408 
6409  CONNECTION_UNLOCK (connection);
6410 }
6411 #endif /* DBUS_ENABLE_STATS */
6412 
6420 long
6422 {
6423  long res;
6424 
6425  _dbus_return_val_if_fail (connection != NULL, 0);
6426 
6427  CONNECTION_LOCK (connection);
6429  CONNECTION_UNLOCK (connection);
6430  return res;
6431 }
6432 
6433 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
6440 const char*
6441 _dbus_connection_get_address (DBusConnection *connection)
6442 {
6443  return _dbus_transport_get_address (connection->transport);
6444 }
6445 #endif
6446 
void dbus_address_entries_free(DBusAddressEntry **entries)
Frees a NULL-terminated array of address entries.
Definition: dbus-address.c:192
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:366
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:247
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:388
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.
DBusMessage * _dbus_connection_get_message_to_send(DBusConnection *connection)
Gets the next outgoing message.
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.
DBusConnection * _dbus_connection_ref_unlocked(DBusConnection *connection)
Increments the reference count of a DBusConnection.
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.
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...
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_builtin_filters_enabled(DBusConnection *connection, dbus_bool_t value)
Enables the builtin filtering of messages.
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_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
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...
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:70
#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:1460
void * _dbus_hash_iter_get_value(DBusHashIter *iter)
Gets the value of the current entry.
Definition: dbus-hash.c:619
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:1311
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:1277
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:367
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:549
void _dbus_hash_iter_init(DBusHashTable *table, DBusHashIter *iter)
Initializes a hash table iterator.
Definition: dbus-hash.c:523
DBusHashTable * _dbus_hash_table_new(DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function)
Constructs a new hash table.
Definition: dbus-hash.c:291
dbus_bool_t _dbus_hash_table_remove_int(DBusHashTable *table, int key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1214
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:1186
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:1112
void _dbus_hash_iter_remove_entry(DBusHashIter *iter)
Removes the current entry from the hash table.
Definition: dbus-hash.c:598
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:1137
@ 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...
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.
char * _dbus_strdup(const char *str)
Duplicates a string.
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.
void * _dbus_list_get_last(DBusList **list)
Gets the last data in the list.
Definition: dbus-list.c:624
dbus_bool_t _dbus_list_copy(DBusList **list, DBusList **dest)
Copies a list.
Definition: dbus-list.c:725
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:595
dbus_bool_t _dbus_list_remove(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:416
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:316
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition: dbus-list.c:640
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition: dbus-list.c:568
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:528
DBusList * _dbus_list_get_last_link(DBusList **list)
Gets the last link in the list.
Definition: dbus-list.c:608
void _dbus_list_unlink(DBusList **list, DBusList *link)
Removes the given link from the list, but doesn't free it.
Definition: dbus-list.c:500
#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:120
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:255
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:787
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:543
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:656
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:334
dbus_bool_t _dbus_list_prepend(DBusList **list, void *data)
Prepends a value to the list.
Definition: dbus-list.c:293
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:243
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:677
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
#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:119
#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:772
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:801
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:692
#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:740
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:289
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:419
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:387
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:315
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_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.
DBusObjectTree * _dbus_object_tree_new(DBusConnection *connection)
Creates a new object tree, representing a mapping from paths to handler vtables.
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.
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...
void _dbus_pending_call_finish_completion(DBusPendingCall *pending)
Call the notifier function for the pending call.
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.
DBUS_PRIVATE_EXPORT DBusPendingCall * _dbus_pending_call_new_unlocked(DBusConnection *connection, int timeout_milliseconds, DBusTimeoutHandler timeout_handler)
Creates a new pending reply object.
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,...
DBusConnection * _dbus_pending_call_get_connection_and_lock(DBusPendingCall *pending)
Gets the connection associated with this pending call.
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.
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.
DBusTimeout * _dbus_pending_call_get_timeout_unlocked(DBusPendingCall *pending)
Retrives the timeout.
#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.
DBusConnection * _dbus_pending_call_get_connection_unlocked(DBusPendingCall *pending)
Gets the connection associated with this pending call.
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.
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.
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_new(void)
Creates a new DBusCounter.
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:182
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
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:1145
void _dbus_exit(int code)
Exit the process, returning the given value.
void _dbus_atomic_set_nonzero(DBusAtomic *atomic)
Atomically set the value of an integer to something nonzero.
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.
void _dbus_atomic_set_zero(DBusAtomic *atomic)
Atomically set the value of an integer to 0.
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:54
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:108
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a condition variable; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:225
DBUS_PRIVATE_EXPORT void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:151
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:241
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition: dbus-threads.c:200
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:78
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition: dbus-threads.c:279
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:262
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:137
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:165
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:95
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:312
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:364
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:241
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:342
DBUS_EXPORT int dbus_timeout_get_interval(DBusTimeout *timeout)
Gets the timeout interval.
Definition: dbus-timeout.c:442
void _dbus_transport_set_max_message_size(DBusTransport *transport, long size)
See dbus_connection_set_max_message_size().
DBusTransport * _dbus_transport_open(DBusAddressEntry *entry, DBusError *error)
Try to open a new transport for the given address entry.
void _dbus_transport_set_max_received_size(DBusTransport *transport, long size)
See dbus_connection_set_max_received_size().
DBusTransport * _dbus_transport_ref(DBusTransport *transport)
Increments the reference count for the transport.
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.
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...
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().
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_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().
DBusCredentials * _dbus_transport_get_credentials(DBusTransport *transport)
If the transport has already been authenticated, return its credentials.
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...
const char * _dbus_transport_get_address(DBusTransport *transport)
Gets the address of a transport.
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().
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
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:381
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:441
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:295
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:414
Internals of DBusAddressEntry.
Definition: dbus-address.c:47
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:324
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.
unsigned int builtin_filters_enabled
If TRUE, handle org.freedesktop.DBus.Peer messages automatically, whether they have a bus name or not...
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:174
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:181
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