dbus-connection.c
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-connection.c DBusConnection object
*
* Copyright (C) 2002-2006 Red Hat Inc.
*
* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <config.h>
#include "dbus-shared.h"
#include "dbus-connection.h"
#include "dbus-list.h"
#include "dbus-timeout.h"
#include "dbus-transport.h"
#include "dbus-watch.h"
#include "dbus-connection-internal.h"
#include "dbus-pending-call-internal.h"
#include "dbus-list.h"
#include "dbus-hash.h"
#include "dbus-message-internal.h"
#include "dbus-message-private.h"
#include "dbus-threads.h"
#include "dbus-protocol.h"
#include "dbus-dataslot.h"
#include "dbus-string.h"
#include "dbus-signature.h"
#include "dbus-pending-call.h"
#include "dbus-object-tree.h"
#include "dbus-threads-internal.h"
#include "dbus-bus.h"
#include "dbus-marshal-basic.h"
#ifdef DBUS_DISABLE_CHECKS
#define TOOK_LOCK_CHECK(connection)
#define RELEASING_LOCK_CHECK(connection)
#define HAVE_LOCK_CHECK(connection)
#else
#define TOOK_LOCK_CHECK(connection) do { \
_dbus_assert (!(connection)->have_connection_lock); \
(connection)->have_connection_lock = TRUE; \
} while (0)
#define RELEASING_LOCK_CHECK(connection) do { \
_dbus_assert ((connection)->have_connection_lock); \
(connection)->have_connection_lock = FALSE; \
} while (0)
#define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
/* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
#endif
#define TRACE_LOCKS 1
#define CONNECTION_LOCK(connection) do { \
if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
_dbus_rmutex_lock ((connection)->mutex); \
TOOK_LOCK_CHECK (connection); \
} while (0)
#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
#define SLOTS_LOCK(connection) do { \
_dbus_rmutex_lock ((connection)->slot_mutex); \
} while (0)
#define SLOTS_UNLOCK(connection) do { \
_dbus_rmutex_unlock ((connection)->slot_mutex); \
} while (0)
#define DISPATCH_STATUS_NAME(s) \
((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
(s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
(s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
"???")
static void
_dbus_connection_trace_ref (DBusConnection *connection,
int old_refcount,
int new_refcount,
const char *why)
{
#ifdef DBUS_ENABLE_VERBOSE_MODE
static int enabled = -1;
_dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
why, "DBUS_CONNECTION_TRACE", &enabled);
#endif
}
typedef struct DBusMessageFilter DBusMessageFilter;
struct DBusMessageFilter
{
DBusAtomic refcount;
DBusHandleMessageFunction function;
void *user_data;
DBusFreeFunction free_user_data_function;
};
struct DBusPreallocatedSend
{
DBusConnection *connection;
DBusList *queue_link;
DBusList *counter_link;
};
#if HAVE_DECL_MSG_NOSIGNAL
static DBusAtomic _dbus_modify_sigpipe = { FALSE };
#else
static DBusAtomic _dbus_modify_sigpipe = { TRUE };
#endif
struct DBusConnection
{
DBusAtomic refcount;
DBusRMutex *mutex;
DBusCMutex *dispatch_mutex;
DBusCondVar *dispatch_cond;
DBusCMutex *io_path_mutex;
DBusCondVar *io_path_cond;
DBusList *outgoing_messages;
DBusList *incoming_messages;
DBusList *expired_messages;
DBusMessage *message_borrowed;
int n_outgoing;
int n_incoming;
DBusCounter *outgoing_counter;
DBusTransport *transport;
DBusWatchList *watches;
DBusTimeoutList *timeouts;
DBusList *filter_list;
DBusRMutex *slot_mutex;
DBusDataSlotList slot_list;
DBusHashTable *pending_replies;
dbus_uint32_t client_serial;
DBusList *disconnect_message_link;
DBusWakeupMainFunction wakeup_main_function;
void *wakeup_main_data;
DBusFreeFunction free_wakeup_main_data;
DBusDispatchStatusFunction dispatch_status_function;
void *dispatch_status_data;
DBusFreeFunction free_dispatch_status_data;
DBusDispatchStatus last_dispatch_status;
DBusObjectTree *objects;
char *server_guid;
/* These two MUST be bools and not bitfields, because they are protected by a separate lock
* from connection->mutex and all bitfields in a word have to be read/written together.
* So you can't have a different lock for different bitfields in the same word.
*/
dbus_bool_t dispatch_acquired;
dbus_bool_t io_path_acquired;
unsigned int shareable : 1;
unsigned int exit_on_disconnect : 1;
unsigned int builtin_filters_enabled : 1;
unsigned int route_peer_messages : 1;
unsigned int disconnected_message_arrived : 1;
unsigned int disconnected_message_processed : 1;
#ifndef DBUS_DISABLE_CHECKS
unsigned int have_connection_lock : 1;
#endif
#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
int generation;
#endif
};
static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
DBusDispatchStatus new_status);
static void _dbus_connection_last_unref (DBusConnection *connection);
static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
static void _dbus_connection_release_dispatch (DBusConnection *connection);
static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
dbus_uint32_t client_serial);
static DBusMessageFilter *
_dbus_message_filter_ref (DBusMessageFilter *filter)
{
#ifdef DBUS_DISABLE_ASSERT
_dbus_atomic_inc (&filter->refcount);
#else
dbus_int32_t old_value;
old_value = _dbus_atomic_inc (&filter->refcount);
_dbus_assert (old_value > 0);
#endif
return filter;
}
static void
_dbus_message_filter_unref (DBusMessageFilter *filter)
{
dbus_int32_t old_value;
old_value = _dbus_atomic_dec (&filter->refcount);
_dbus_assert (old_value > 0);
if (old_value == 1)
{
if (filter->free_user_data_function)
(* filter->free_user_data_function) (filter->user_data);
dbus_free (filter);
}
}
void
_dbus_connection_lock (DBusConnection *connection)
{
CONNECTION_LOCK (connection);
}
void
_dbus_connection_unlock (DBusConnection *connection)
{
DBusList *expired_messages;
DBusList *iter;
if (TRACE_LOCKS)
{
_dbus_verbose ("UNLOCK\n");
}
/* If we had messages that expired (fell off the incoming or outgoing
* queues) while we were locked, actually release them now */
expired_messages = connection->expired_messages;
connection->expired_messages = NULL;
RELEASING_LOCK_CHECK (connection);
_dbus_rmutex_unlock (connection->mutex);
for (iter = _dbus_list_pop_first_link (&expired_messages);
iter != NULL;
iter = _dbus_list_pop_first_link (&expired_messages))
{
DBusMessage *message = iter->data;
dbus_message_unref (message);
_dbus_list_free_link (iter);
}
}
static void
_dbus_connection_wakeup_mainloop (DBusConnection *connection)
{
if (connection->wakeup_main_function)
(*connection->wakeup_main_function) (connection->wakeup_main_data);
}
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
void
_dbus_connection_test_get_locks (DBusConnection *connection,
DBusMutex **mutex_loc,
DBusMutex **dispatch_mutex_loc,
DBusMutex **io_path_mutex_loc,
DBusCondVar **dispatch_cond_loc,
DBusCondVar **io_path_cond_loc)
{
*mutex_loc = (DBusMutex *) connection->mutex;
*dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
*io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
*dispatch_cond_loc = connection->dispatch_cond;
*io_path_cond_loc = connection->io_path_cond;
}
#endif
void
_dbus_connection_queue_received_message_link (DBusConnection *connection,
DBusList *link)
{
DBusPendingCall *pending;
dbus_uint32_t reply_serial;
DBusMessage *message;
_dbus_assert (_dbus_transport_peek_is_authenticated (connection->transport));
_dbus_list_append_link (&connection->incoming_messages,
link);
message = link->data;
/* If this is a reply we're waiting on, remove timeout for it */
reply_serial = dbus_message_get_reply_serial (message);
if (reply_serial != 0)
{
pending = _dbus_hash_table_lookup_int (connection->pending_replies,
reply_serial);
if (pending != NULL)
{
if (_dbus_pending_call_is_timeout_added_unlocked (pending))
_dbus_connection_remove_timeout_unlocked (connection,
_dbus_pending_call_get_timeout_unlocked (pending));
_dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
}
}
connection->n_incoming += 1;
_dbus_connection_wakeup_mainloop (connection);
_dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
message,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_path (message) ?
dbus_message_get_path (message) :
"no path",
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
"no interface",
dbus_message_get_member (message) ?
dbus_message_get_member (message) :
"no member",
dbus_message_get_signature (message),
dbus_message_get_reply_serial (message),
connection,
connection->n_incoming);
_dbus_message_trace_ref (message, -1, -1,
"_dbus_conection_queue_received_message_link");
}
void
_dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
DBusList *link)
{
HAVE_LOCK_CHECK (connection);
_dbus_list_append_link (&connection->incoming_messages, link);
connection->n_incoming += 1;
_dbus_connection_wakeup_mainloop (connection);
_dbus_message_trace_ref (link->data, -1, -1,
"_dbus_connection_queue_synthesized_message_link");
_dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
link->data, connection, connection->n_incoming);
}
dbus_bool_t
_dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
return connection->outgoing_messages != NULL;
}
dbus_bool_t
dbus_connection_has_messages_to_send (DBusConnection *connection)
{
dbus_bool_t v;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
v = _dbus_connection_has_messages_to_send_unlocked (connection);
CONNECTION_UNLOCK (connection);
return v;
}
DBusMessage*
_dbus_connection_get_message_to_send (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
return _dbus_list_get_last (&connection->outgoing_messages);
}
void
_dbus_connection_message_sent_unlocked (DBusConnection *connection,
DBusMessage *message)
{
DBusList *link;
HAVE_LOCK_CHECK (connection);
/* This can be called before we even complete authentication, since
* it's called on disconnect to clean up the outgoing queue.
* It's also called as we successfully send each message.
*/
link = _dbus_list_get_last_link (&connection->outgoing_messages);
_dbus_assert (link != NULL);
_dbus_assert (link->data == message);
_dbus_list_unlink (&connection->outgoing_messages,
link);
_dbus_list_prepend_link (&connection->expired_messages, link);
connection->n_outgoing -= 1;
_dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
message,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_path (message) ?
dbus_message_get_path (message) :
"no path",
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
"no interface",
dbus_message_get_member (message) ?
dbus_message_get_member (message) :
"no member",
dbus_message_get_signature (message),
connection, connection->n_outgoing);
/* It's OK that in principle we call the notify function, because for the
* outgoing limit, there isn't one */
_dbus_message_remove_counter (message, connection->outgoing_counter);
/* The message will actually be unreffed when we unlock */
}
typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
DBusWatch *watch);
typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
DBusWatch *watch);
typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
DBusWatch *watch,
dbus_bool_t enabled);
static dbus_bool_t
protected_change_watch (DBusConnection *connection,
DBusWatch *watch,
DBusWatchAddFunction add_function,
DBusWatchRemoveFunction remove_function,
DBusWatchToggleFunction toggle_function,
dbus_bool_t enabled)
{
dbus_bool_t retval;
HAVE_LOCK_CHECK (connection);
/* The original purpose of protected_change_watch() was to hold a
* ref on the connection while dropping the connection lock, then
* calling out to the app. This was a broken hack that did not
* work, since the connection was in a hosed state (no WatchList
* field) while calling out.
*
* So for now we'll just keep the lock while calling out. This means
* apps are not allowed to call DBusConnection methods inside a
* watch function or they will deadlock.
*
* The "real fix" is to use the _and_unlock() pattern found
* elsewhere in the code, to defer calling out to the app until
* we're about to drop locks and return flow of control to the app
* anyway.
*
* See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
*/
if (connection->watches)
{
if (add_function)
retval = (* add_function) (connection->watches, watch);
else if (remove_function)
{
retval = TRUE;
(* remove_function) (connection->watches, watch);
}
else
{
retval = TRUE;
(* toggle_function) (connection->watches, watch, enabled);
}
return retval;
}
else
return FALSE;
}
dbus_bool_t
_dbus_connection_add_watch_unlocked (DBusConnection *connection,
DBusWatch *watch)
{
return protected_change_watch (connection, watch,
_dbus_watch_list_add_watch,
NULL, NULL, FALSE);
}
void
_dbus_connection_remove_watch_unlocked (DBusConnection *connection,
DBusWatch *watch)
{
protected_change_watch (connection, watch,
NULL,
_dbus_watch_list_remove_watch,
NULL, FALSE);
}
void
_dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
DBusWatch *watch,
dbus_bool_t enabled)
{
_dbus_assert (watch != NULL);
protected_change_watch (connection, watch,
NULL, NULL,
_dbus_watch_list_toggle_watch,
enabled);
}
typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
DBusTimeout *timeout);
typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
DBusTimeout *timeout);
typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
DBusTimeout *timeout,
dbus_bool_t enabled);
static dbus_bool_t
protected_change_timeout (DBusConnection *connection,
DBusTimeout *timeout,
DBusTimeoutAddFunction add_function,
DBusTimeoutRemoveFunction remove_function,
DBusTimeoutToggleFunction toggle_function,
dbus_bool_t enabled)
{
dbus_bool_t retval;
HAVE_LOCK_CHECK (connection);
/* The original purpose of protected_change_timeout() was to hold a
* ref on the connection while dropping the connection lock, then
* calling out to the app. This was a broken hack that did not
* work, since the connection was in a hosed state (no TimeoutList
* field) while calling out.
*
* So for now we'll just keep the lock while calling out. This means
* apps are not allowed to call DBusConnection methods inside a
* timeout function or they will deadlock.
*
* The "real fix" is to use the _and_unlock() pattern found
* elsewhere in the code, to defer calling out to the app until
* we're about to drop locks and return flow of control to the app
* anyway.
*
* See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
*/
if (connection->timeouts)
{
if (add_function)
retval = (* add_function) (connection->timeouts, timeout);
else if (remove_function)
{
retval = TRUE;
(* remove_function) (connection->timeouts, timeout);
}
else
{
retval = TRUE;
(* toggle_function) (connection->timeouts, timeout, enabled);
}
return retval;
}
else
return FALSE;
}
dbus_bool_t
_dbus_connection_add_timeout_unlocked (DBusConnection *connection,
DBusTimeout *timeout)
{
return protected_change_timeout (connection, timeout,
_dbus_timeout_list_add_timeout,
NULL, NULL, FALSE);
}
void
_dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
DBusTimeout *timeout)
{
protected_change_timeout (connection, timeout,
NULL,
_dbus_timeout_list_remove_timeout,
NULL, FALSE);
}
void
_dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
DBusTimeout *timeout,
dbus_bool_t enabled)
{
protected_change_timeout (connection, timeout,
NULL, NULL,
_dbus_timeout_list_toggle_timeout,
enabled);
}
static dbus_bool_t
_dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
DBusPendingCall *pending)
{
dbus_uint32_t reply_serial;
DBusTimeout *timeout;
HAVE_LOCK_CHECK (connection);
reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
_dbus_assert (reply_serial != 0);
timeout = _dbus_pending_call_get_timeout_unlocked (pending);
if (timeout)
{
if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
return FALSE;
if (!_dbus_hash_table_insert_int (connection->pending_replies,
reply_serial,
pending))
{
_dbus_connection_remove_timeout_unlocked (connection, timeout);
_dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
HAVE_LOCK_CHECK (connection);
return FALSE;
}
_dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
}
else
{
if (!_dbus_hash_table_insert_int (connection->pending_replies,
reply_serial,
pending))
{
HAVE_LOCK_CHECK (connection);
return FALSE;
}
}
_dbus_pending_call_ref_unlocked (pending);
HAVE_LOCK_CHECK (connection);
return TRUE;
}
static void
free_pending_call_on_hash_removal (void *data)
{
DBusPendingCall *pending;
DBusConnection *connection;
if (data == NULL)
return;
pending = data;
connection = _dbus_pending_call_get_connection_unlocked (pending);
HAVE_LOCK_CHECK (connection);
if (_dbus_pending_call_is_timeout_added_unlocked (pending))
{
_dbus_connection_remove_timeout_unlocked (connection,
_dbus_pending_call_get_timeout_unlocked (pending));
_dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
}
/* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock
* here, but the pending call finalizer could in principle call out to
* application code so we pretty much have to... some larger code reorg
* might be needed.
*/
_dbus_connection_ref_unlocked (connection);
_dbus_pending_call_unref_and_unlock (pending);
CONNECTION_LOCK (connection);
_dbus_connection_unref_unlocked (connection);
}
static void
_dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
DBusPendingCall *pending)
{
/* This ends up unlocking to call the pending call finalizer, which is unexpected to
* say the least.
*/
_dbus_hash_table_remove_int (connection->pending_replies,
_dbus_pending_call_get_reply_serial_unlocked (pending));
}
static void
_dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
DBusPendingCall *pending)
{
/* The idea here is to avoid finalizing the pending call
* with the lock held, since there's a destroy notifier
* in pending call that goes out to application code.
*
* There's an extra unlock inside the hash table
* "free pending call" function FIXME...
*/
_dbus_pending_call_ref_unlocked (pending);
_dbus_hash_table_remove_int (connection->pending_replies,
_dbus_pending_call_get_reply_serial_unlocked (pending));
if (_dbus_pending_call_is_timeout_added_unlocked (pending))
_dbus_connection_remove_timeout_unlocked (connection,
_dbus_pending_call_get_timeout_unlocked (pending));
_dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
_dbus_pending_call_unref_and_unlock (pending);
}
void
_dbus_connection_remove_pending_call (DBusConnection *connection,
DBusPendingCall *pending)
{
CONNECTION_LOCK (connection);
_dbus_connection_detach_pending_call_and_unlock (connection, pending);
}
static dbus_bool_t
_dbus_connection_acquire_io_path (DBusConnection *connection,
int timeout_milliseconds)
{
dbus_bool_t we_acquired;
HAVE_LOCK_CHECK (connection);
/* We don't want the connection to vanish */
_dbus_connection_ref_unlocked (connection);
/* We will only touch io_path_acquired which is protected by our mutex */
CONNECTION_UNLOCK (connection);
_dbus_verbose ("locking io_path_mutex\n");
_dbus_cmutex_lock (connection->io_path_mutex);
_dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
connection->io_path_acquired, timeout_milliseconds);
we_acquired = FALSE;
if (connection->io_path_acquired)
{
if (timeout_milliseconds != -1)
{
_dbus_verbose ("waiting %d for IO path to be acquirable\n",
timeout_milliseconds);
if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
connection->io_path_mutex,
timeout_milliseconds))
{
/* We timed out before anyone signaled. */
/* (writing the loop to handle the !timedout case by
* waiting longer if needed is a pain since dbus
* wraps pthread_cond_timedwait to take a relative
* time instead of absolute, something kind of stupid
* on our part. for now it doesn't matter, we will just
* end up back here eventually.)
*/
}
}
else
{
while (connection->io_path_acquired)
{
_dbus_verbose ("waiting for IO path to be acquirable\n");
_dbus_condvar_wait (connection->io_path_cond,
connection->io_path_mutex);
}
}
}
if (!connection->io_path_acquired)
{
we_acquired = TRUE;
connection->io_path_acquired = TRUE;
}
_dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
connection->io_path_acquired, we_acquired);
_dbus_verbose ("unlocking io_path_mutex\n");
_dbus_cmutex_unlock (connection->io_path_mutex);
CONNECTION_LOCK (connection);
HAVE_LOCK_CHECK (connection);
_dbus_connection_unref_unlocked (connection);
return we_acquired;
}
static void
_dbus_connection_release_io_path (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
_dbus_verbose ("locking io_path_mutex\n");
_dbus_cmutex_lock (connection->io_path_mutex);
_dbus_assert (connection->io_path_acquired);
_dbus_verbose ("start connection->io_path_acquired = %d\n",
connection->io_path_acquired);
connection->io_path_acquired = FALSE;
_dbus_condvar_wake_one (connection->io_path_cond);
_dbus_verbose ("unlocking io_path_mutex\n");
_dbus_cmutex_unlock (connection->io_path_mutex);
}
void
_dbus_connection_do_iteration_unlocked (DBusConnection *connection,
DBusPendingCall *pending,
unsigned int flags,
int timeout_milliseconds)
{
_dbus_verbose ("start\n");
HAVE_LOCK_CHECK (connection);
if (connection->n_outgoing == 0)
flags &= ~DBUS_ITERATION_DO_WRITING;
if (_dbus_connection_acquire_io_path (connection,
(flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
{
HAVE_LOCK_CHECK (connection);
if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
{
_dbus_verbose ("pending call completed while acquiring I/O path");
}
else if ( (pending != NULL) &&
_dbus_connection_peek_for_reply_unlocked (connection,
_dbus_pending_call_get_reply_serial_unlocked (pending)))
{
_dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
}
else
{
_dbus_transport_do_iteration (connection->transport,
flags, timeout_milliseconds);
}
_dbus_connection_release_io_path (connection);
}
HAVE_LOCK_CHECK (connection);
_dbus_verbose ("end\n");
}
DBusConnection*
_dbus_connection_new_for_transport (DBusTransport *transport)
{
DBusConnection *connection;
DBusWatchList *watch_list;
DBusTimeoutList *timeout_list;
DBusHashTable *pending_replies;
DBusList *disconnect_link;
DBusMessage *disconnect_message;
DBusCounter *outgoing_counter;
DBusObjectTree *objects;
watch_list = NULL;
connection = NULL;
pending_replies = NULL;
timeout_list = NULL;
disconnect_link = NULL;
disconnect_message = NULL;
outgoing_counter = NULL;
objects = NULL;
watch_list = _dbus_watch_list_new ();
if (watch_list == NULL)
goto error;
timeout_list = _dbus_timeout_list_new ();
if (timeout_list == NULL)
goto error;
pending_replies =
_dbus_hash_table_new (DBUS_HASH_INT,
NULL,
(DBusFreeFunction)free_pending_call_on_hash_removal);
if (pending_replies == NULL)
goto error;
connection = dbus_new0 (DBusConnection, 1);
if (connection == NULL)
goto error;
_dbus_rmutex_new_at_location (&connection->mutex);
if (connection->mutex == NULL)
goto error;
_dbus_cmutex_new_at_location (&connection->io_path_mutex);
if (connection->io_path_mutex == NULL)
goto error;
_dbus_cmutex_new_at_location (&connection->dispatch_mutex);
if (connection->dispatch_mutex == NULL)
goto error;
_dbus_condvar_new_at_location (&connection->dispatch_cond);
if (connection->dispatch_cond == NULL)
goto error;
_dbus_condvar_new_at_location (&connection->io_path_cond);
if (connection->io_path_cond == NULL)
goto error;
_dbus_rmutex_new_at_location (&connection->slot_mutex);
if (connection->slot_mutex == NULL)
goto error;
disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
DBUS_INTERFACE_LOCAL,
"Disconnected");
if (disconnect_message == NULL)
goto error;
disconnect_link = _dbus_list_alloc_link (disconnect_message);
if (disconnect_link == NULL)
goto error;
outgoing_counter = _dbus_counter_new ();
if (outgoing_counter == NULL)
goto error;
objects = _dbus_object_tree_new (connection);
if (objects == NULL)
goto error;
if (_dbus_atomic_get (&_dbus_modify_sigpipe) != 0)
_dbus_disable_sigpipe ();
/* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
_dbus_atomic_inc (&connection->refcount);
connection->transport = transport;
connection->watches = watch_list;
connection->timeouts = timeout_list;
connection->pending_replies = pending_replies;
connection->outgoing_counter = outgoing_counter;
connection->filter_list = NULL;
connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
connection->objects = objects;
connection->exit_on_disconnect = FALSE;
connection->shareable = FALSE;
connection->builtin_filters_enabled = TRUE;
connection->route_peer_messages = FALSE;
connection->disconnected_message_arrived = FALSE;
connection->disconnected_message_processed = FALSE;
#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
connection->generation = _dbus_current_generation;
#endif
_dbus_data_slot_list_init (&connection->slot_list);
connection->client_serial = 1;
connection->disconnect_message_link = disconnect_link;
CONNECTION_LOCK (connection);
if (!_dbus_transport_set_connection (transport, connection))
{
CONNECTION_UNLOCK (connection);
goto error;
}
_dbus_transport_ref (transport);
CONNECTION_UNLOCK (connection);
_dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
return connection;
error:
if (disconnect_message != NULL)
dbus_message_unref (disconnect_message);
if (disconnect_link != NULL)
_dbus_list_free_link (disconnect_link);
if (connection != NULL)
{
_dbus_condvar_free_at_location (&connection->io_path_cond);
_dbus_condvar_free_at_location (&connection->dispatch_cond);
_dbus_rmutex_free_at_location (&connection->mutex);
_dbus_cmutex_free_at_location (&connection->io_path_mutex);
_dbus_cmutex_free_at_location (&connection->dispatch_mutex);
_dbus_rmutex_free_at_location (&connection->slot_mutex);
dbus_free (connection);
}
if (pending_replies)
_dbus_hash_table_unref (pending_replies);
if (watch_list)
_dbus_watch_list_free (watch_list);
if (timeout_list)
_dbus_timeout_list_free (timeout_list);
if (outgoing_counter)
_dbus_counter_unref (outgoing_counter);
if (objects)
_dbus_object_tree_unref (objects);
return NULL;
}
DBusConnection *
_dbus_connection_ref_unlocked (DBusConnection *connection)
{
dbus_int32_t old_refcount;
_dbus_assert (connection != NULL);
_dbus_assert (connection->generation == _dbus_current_generation);
HAVE_LOCK_CHECK (connection);
old_refcount = _dbus_atomic_inc (&connection->refcount);
_dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
"ref_unlocked");
return connection;
}
void
_dbus_connection_unref_unlocked (DBusConnection *connection)
{
dbus_int32_t old_refcount;
HAVE_LOCK_CHECK (connection);
_dbus_assert (connection != NULL);
old_refcount = _dbus_atomic_dec (&connection->refcount);
_dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
"unref_unlocked");
if (old_refcount == 1)
_dbus_connection_last_unref (connection);
}
dbus_uint32_t
_dbus_connection_get_next_client_serial (DBusConnection *connection)
{
dbus_uint32_t serial;
serial = connection->client_serial++;
if (connection->client_serial == 0)
connection->client_serial = 1;
return serial;
}
dbus_bool_t
_dbus_connection_handle_watch (DBusWatch *watch,
unsigned int condition,
void *data)
{
DBusConnection *connection;
dbus_bool_t retval;
DBusDispatchStatus status;
connection = data;
_dbus_verbose ("start\n");
CONNECTION_LOCK (connection);
if (!_dbus_connection_acquire_io_path (connection, 1))
{
/* another thread is handling the message */
CONNECTION_UNLOCK (connection);
return TRUE;
}
HAVE_LOCK_CHECK (connection);
retval = _dbus_transport_handle_watch (connection->transport,
watch, condition);
_dbus_connection_release_io_path (connection);
HAVE_LOCK_CHECK (connection);
_dbus_verbose ("middle\n");
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* this calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
_dbus_verbose ("end\n");
return retval;
}
/* Protected by _DBUS_LOCK (shared_connections) */
static DBusHashTable *shared_connections = NULL;
static DBusList *shared_connections_no_guid = NULL;
static void
close_connection_on_shutdown (DBusConnection *connection)
{
DBusMessage *message;
dbus_connection_ref (connection);
_dbus_connection_close_possibly_shared (connection);
/* Churn through to the Disconnected message */
while ((message = dbus_connection_pop_message (connection)))
{
dbus_message_unref (message);
}
dbus_connection_unref (connection);
}
static void
shared_connections_shutdown (void *data)
{
int n_entries;
if (!_DBUS_LOCK (shared_connections))
{
/* We'd have initialized locks before adding anything, so there
* can't be anything there. */
return;
}
/* This is a little bit unpleasant... better ideas? */
while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
{
DBusConnection *connection;
DBusHashIter iter;
_dbus_hash_iter_init (shared_connections, &iter);
_dbus_hash_iter_next (&iter);
connection = _dbus_hash_iter_get_value (&iter);
_DBUS_UNLOCK (shared_connections);
close_connection_on_shutdown (connection);
if (!_DBUS_LOCK (shared_connections))
_dbus_assert_not_reached ("global locks were already initialized");
/* The connection should now be dead and not in our hash ... */
_dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
}
_dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
_dbus_hash_table_unref (shared_connections);
shared_connections = NULL;
if (shared_connections_no_guid != NULL)
{
DBusConnection *connection;
connection = _dbus_list_pop_first (&shared_connections_no_guid);
while (connection != NULL)
{
_DBUS_UNLOCK (shared_connections);
close_connection_on_shutdown (connection);
if (!_DBUS_LOCK (shared_connections))
_dbus_assert_not_reached ("global locks were already initialized");
connection = _dbus_list_pop_first (&shared_connections_no_guid);
}
}
shared_connections_no_guid = NULL;
_DBUS_UNLOCK (shared_connections);
}
static dbus_bool_t
connection_lookup_shared (DBusAddressEntry *entry,
DBusConnection **result)
{
_dbus_verbose ("checking for existing connection\n");
*result = NULL;
if (!_DBUS_LOCK (shared_connections))
{
/* If it was shared, we'd have initialized global locks when we put
* it in shared_connections. */
return FALSE;
}
if (shared_connections == NULL)
{
_dbus_verbose ("creating shared_connections hash table\n");
shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
dbus_free,
NULL);
if (shared_connections == NULL)
{
_DBUS_UNLOCK (shared_connections);
return FALSE;
}
if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
{
_dbus_hash_table_unref (shared_connections);
shared_connections = NULL;
_DBUS_UNLOCK (shared_connections);
return FALSE;
}
_dbus_verbose (" successfully created shared_connections\n");
_DBUS_UNLOCK (shared_connections);
return TRUE; /* no point looking up in the hash we just made */
}
else
{
const char *guid;
guid = dbus_address_entry_get_value (entry, "guid");
if (guid != NULL)
{
DBusConnection *connection;
connection = _dbus_hash_table_lookup_string (shared_connections,
guid);
if (connection)
{
/* The DBusConnection can't be finalized without taking
* the shared_connections lock to remove it from the
* hash. So it's safe to ref the connection here.
* However, it may be disconnected if the Disconnected
* message hasn't been processed yet, in which case we
* want to pretend it isn't in the hash and avoid
* returning it.
*
* The idea is to avoid ever returning a disconnected connection
* from dbus_connection_open(). We could just synchronously
* drop our shared ref to the connection on connection disconnect,
* and then assert here that the connection is connected, but
* that causes reentrancy headaches.
*/
CONNECTION_LOCK (connection);
if (_dbus_connection_get_is_connected_unlocked (connection))
{
_dbus_connection_ref_unlocked (connection);
*result = connection;
_dbus_verbose ("looked up existing connection to server guid %s\n",
guid);
}
else
{
_dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
guid);
}
CONNECTION_UNLOCK (connection);
}
}
_DBUS_UNLOCK (shared_connections);
return TRUE;
}
}
static dbus_bool_t
connection_record_shared_unlocked (DBusConnection *connection,
const char *guid)
{
char *guid_key;
char *guid_in_connection;
HAVE_LOCK_CHECK (connection);
_dbus_assert (connection->server_guid == NULL);
_dbus_assert (connection->shareable);
/* get a hard ref on this connection, even if
* we won't in fact store it in the hash, we still
* need to hold a ref on it until it's disconnected.
*/
_dbus_connection_ref_unlocked (connection);
if (guid == NULL)
{
if (!_DBUS_LOCK (shared_connections))
return FALSE;
if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
{
_DBUS_UNLOCK (shared_connections);
return FALSE;
}
_DBUS_UNLOCK (shared_connections);
return TRUE; /* don't store in the hash */
}
/* A separate copy of the key is required in the hash table, because
* we don't have a lock on the connection when we are doing a hash
* lookup.
*/
guid_key = _dbus_strdup (guid);
if (guid_key == NULL)
return FALSE;
guid_in_connection = _dbus_strdup (guid);
if (guid_in_connection == NULL)
{
dbus_free (guid_key);
return FALSE;
}
if (!_DBUS_LOCK (shared_connections))
{
dbus_free (guid_in_connection);
dbus_free (guid_key);
return FALSE;
}
_dbus_assert (shared_connections != NULL);
if (!_dbus_hash_table_insert_string (shared_connections,
guid_key, connection))
{
dbus_free (guid_key);
dbus_free (guid_in_connection);
_DBUS_UNLOCK (shared_connections);
return FALSE;
}
connection->server_guid = guid_in_connection;
_dbus_verbose ("stored connection to %s to be shared\n",
connection->server_guid);
_DBUS_UNLOCK (shared_connections);
_dbus_assert (connection->server_guid != NULL);
return TRUE;
}
static void
connection_forget_shared_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
if (!connection->shareable)
return;
if (!_DBUS_LOCK (shared_connections))
{
/* If it was shared, we'd have initialized global locks when we put
* it in the table; so it can't be there. */
return;
}
if (connection->server_guid != NULL)
{
_dbus_verbose ("dropping connection to %s out of the shared table\n",
connection->server_guid);
if (!_dbus_hash_table_remove_string (shared_connections,
connection->server_guid))
_dbus_assert_not_reached ("connection was not in the shared table");
dbus_free (connection->server_guid);
connection->server_guid = NULL;
}
else
{
_dbus_list_remove (&shared_connections_no_guid, connection);
}
_DBUS_UNLOCK (shared_connections);
/* remove our reference held on all shareable connections */
_dbus_connection_unref_unlocked (connection);
}
static DBusConnection*
connection_try_from_address_entry (DBusAddressEntry *entry,
DBusError *error)
{
DBusTransport *transport;
DBusConnection *connection;
transport = _dbus_transport_open (entry, error);
if (transport == NULL)
{
_DBUS_ASSERT_ERROR_IS_SET (error);
return NULL;
}
connection = _dbus_connection_new_for_transport (transport);
_dbus_transport_unref (transport);
if (connection == NULL)
{
_DBUS_SET_OOM (error);
return NULL;
}
#ifndef DBUS_DISABLE_CHECKS
_dbus_assert (!connection->have_connection_lock);
#endif
return connection;
}
/*
* If the shared parameter is true, then any existing connection will
* be used (and if a new connection is created, it will be available
* for use by others). If the shared parameter is false, a new
* connection will always be created, and the new connection will
* never be returned to other callers.
*
* @param address the address
* @param shared whether the connection is shared or private
* @param error error return
* @returns the connection or #NULL on error
*/
static DBusConnection*
_dbus_connection_open_internal (const char *address,
dbus_bool_t shared,
DBusError *error)
{
DBusConnection *connection;
DBusAddressEntry **entries;
DBusError tmp_error = DBUS_ERROR_INIT;
DBusError first_error = DBUS_ERROR_INIT;
int len, i;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("opening %s connection to: %s\n",
shared ? "shared" : "private", address);
if (!dbus_parse_address (address, &entries, &len, error))
return NULL;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
connection = NULL;
for (i = 0; i < len; i++)
{
if (shared)
{
if (!connection_lookup_shared (entries[i], &connection))
_DBUS_SET_OOM (&tmp_error);
}
if (connection == NULL)
{
connection = connection_try_from_address_entry (entries[i],
&tmp_error);
if (connection != NULL && shared)
{
const char *guid;
connection->shareable = TRUE;
/* guid may be NULL */
guid = dbus_address_entry_get_value (entries[i], "guid");
CONNECTION_LOCK (connection);
if (!connection_record_shared_unlocked (connection, guid))
{
_DBUS_SET_OOM (&tmp_error);
_dbus_connection_close_possibly_shared_and_unlock (connection);
dbus_connection_unref (connection);
connection = NULL;
}
else
CONNECTION_UNLOCK (connection);
}
}
if (connection)
break;
_DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
if (i == 0)
dbus_move_error (&tmp_error, &first_error);
else
dbus_error_free (&tmp_error);
}
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
if (connection == NULL)
{
_DBUS_ASSERT_ERROR_IS_SET (&first_error);
dbus_move_error (&first_error, error);
}
else
dbus_error_free (&first_error);
dbus_address_entries_free (entries);
return connection;
}
void
_dbus_connection_close_possibly_shared (DBusConnection *connection)
{
_dbus_assert (connection != NULL);
_dbus_assert (connection->generation == _dbus_current_generation);
CONNECTION_LOCK (connection);
_dbus_connection_close_possibly_shared_and_unlock (connection);
}
static DBusPreallocatedSend*
_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
{
DBusPreallocatedSend *preallocated;
HAVE_LOCK_CHECK (connection);
_dbus_assert (connection != NULL);
preallocated = dbus_new (DBusPreallocatedSend, 1);
if (preallocated == NULL)
return NULL;
preallocated->queue_link = _dbus_list_alloc_link (NULL);
if (preallocated->queue_link == NULL)
goto failed_0;
preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
if (preallocated->counter_link == NULL)
goto failed_1;
_dbus_counter_ref (preallocated->counter_link->data);
preallocated->connection = connection;
return preallocated;
failed_1:
_dbus_list_free_link (preallocated->queue_link);
failed_0:
dbus_free (preallocated);
return NULL;
}
/* Called with lock held, does not update dispatch status */
static void
_dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
DBusPreallocatedSend *preallocated,
DBusMessage *message,
dbus_uint32_t *client_serial)
{
dbus_uint32_t serial;
preallocated->queue_link->data = message;
_dbus_list_prepend_link (&connection->outgoing_messages,
preallocated->queue_link);
/* It's OK that we'll never call the notify function, because for the
* outgoing limit, there isn't one */
_dbus_message_add_counter_link (message,
preallocated->counter_link);
dbus_free (preallocated);
preallocated = NULL;
dbus_message_ref (message);
connection->n_outgoing += 1;
_dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
message,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_path (message) ?
dbus_message_get_path (message) :
"no path",
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
"no interface",
dbus_message_get_member (message) ?
dbus_message_get_member (message) :
"no member",
dbus_message_get_signature (message),
dbus_message_get_destination (message) ?
dbus_message_get_destination (message) :
"null",
connection,
connection->n_outgoing);
if (dbus_message_get_serial (message) == 0)
{
serial = _dbus_connection_get_next_client_serial (connection);
dbus_message_set_serial (message, serial);
if (client_serial)
*client_serial = serial;
}
else
{
if (client_serial)
*client_serial = dbus_message_get_serial (message);
}
_dbus_verbose ("Message %p serial is %u\n",
message, dbus_message_get_serial (message));
dbus_message_lock (message);
/* Now we need to run an iteration to hopefully just write the messages
* out immediately, and otherwise get them queued up
*/
_dbus_connection_do_iteration_unlocked (connection,
NULL,
DBUS_ITERATION_DO_WRITING,
-1);
/* If stuff is still queued up, be sure we wake up the main loop */
if (connection->n_outgoing > 0)
_dbus_connection_wakeup_mainloop (connection);
}
static void
_dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
DBusPreallocatedSend *preallocated,
DBusMessage *message,
dbus_uint32_t *client_serial)
{
DBusDispatchStatus status;
HAVE_LOCK_CHECK (connection);
_dbus_connection_send_preallocated_unlocked_no_update (connection,
preallocated,
message, client_serial);
_dbus_verbose ("middle\n");
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* this calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
}
dbus_bool_t
_dbus_connection_send_and_unlock (DBusConnection *connection,
DBusMessage *message,
dbus_uint32_t *client_serial)
{
DBusPreallocatedSend *preallocated;
_dbus_assert (connection != NULL);
_dbus_assert (message != NULL);
preallocated = _dbus_connection_preallocate_send_unlocked (connection);
if (preallocated == NULL)
{
CONNECTION_UNLOCK (connection);
return FALSE;
}
_dbus_connection_send_preallocated_and_unlock (connection,
preallocated,
message,
client_serial);
return TRUE;
}
void
_dbus_connection_close_if_only_one_ref (DBusConnection *connection)
{
dbus_int32_t refcount;
CONNECTION_LOCK (connection);
refcount = _dbus_atomic_get (&connection->refcount);
/* The caller should have at least one ref */
_dbus_assert (refcount >= 1);
if (refcount == 1)
_dbus_connection_close_possibly_shared_and_unlock (connection);
else
CONNECTION_UNLOCK (connection);
}
static void
_dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
{
if (timeout_milliseconds == -1)
_dbus_sleep_milliseconds (1000);
else if (timeout_milliseconds < 100)
; /* just busy loop */
else if (timeout_milliseconds <= 1000)
_dbus_sleep_milliseconds (timeout_milliseconds / 3);
else
_dbus_sleep_milliseconds (1000);
}
static DBusMessage *
generate_local_error_message (dbus_uint32_t serial,
const char *error_name,
const char *error_msg)
{
DBusMessage *message;
message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
if (!message)
goto out;
if (!dbus_message_set_error_name (message, error_name))
{
dbus_message_unref (message);
message = NULL;
goto out;
}
dbus_message_set_no_reply (message, TRUE);
if (!dbus_message_set_reply_serial (message,
serial))
{
dbus_message_unref (message);
message = NULL;
goto out;
}
if (error_msg != NULL)
{
DBusMessageIter iter;
dbus_message_iter_init_append (message, &iter);
if (!dbus_message_iter_append_basic (&iter,
DBUS_TYPE_STRING,
&error_msg))
{
dbus_message_unref (message);
message = NULL;
goto out;
}
}
out:
return message;
}
/*
* Peek the incoming queue to see if we got reply for a specific serial
*/
static dbus_bool_t
_dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
dbus_uint32_t client_serial)
{
DBusList *link;
HAVE_LOCK_CHECK (connection);
link = _dbus_list_get_first_link (&connection->incoming_messages);
while (link != NULL)
{
DBusMessage *reply = link->data;
if (dbus_message_get_reply_serial (reply) == client_serial)
{
_dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
return TRUE;
}
link = _dbus_list_get_next_link (&connection->incoming_messages, link);
}
return FALSE;
}
/* This is slightly strange since we can pop a message here without
* the dispatch lock.
*/
static DBusMessage*
check_for_reply_unlocked (DBusConnection *connection,
dbus_uint32_t client_serial)
{
DBusList *link;
HAVE_LOCK_CHECK (connection);
link = _dbus_list_get_first_link (&connection->incoming_messages);
while (link != NULL)
{
DBusMessage *reply = link->data;
if (dbus_message_get_reply_serial (reply) == client_serial)
{
_dbus_list_remove_link (&connection->incoming_messages, link);
connection->n_incoming -= 1;
return reply;
}
link = _dbus_list_get_next_link (&connection->incoming_messages, link);
}
return NULL;
}
static void
connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
{
/* We can't iterate over the hash in the normal way since we'll be
* dropping the lock for each item. So we restart the
* iter each time as we drain the hash table.
*/
while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
{
DBusPendingCall *pending;
DBusHashIter iter;
_dbus_hash_iter_init (connection->pending_replies, &iter);
_dbus_hash_iter_next (&iter);
pending = _dbus_hash_iter_get_value (&iter);
_dbus_pending_call_ref_unlocked (pending);
_dbus_pending_call_queue_timeout_error_unlocked (pending,
connection);
if (_dbus_pending_call_is_timeout_added_unlocked (pending))
_dbus_connection_remove_timeout_unlocked (connection,
_dbus_pending_call_get_timeout_unlocked (pending));
_dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
_dbus_hash_iter_remove_entry (&iter);
_dbus_pending_call_unref_and_unlock (pending);
CONNECTION_LOCK (connection);
}
HAVE_LOCK_CHECK (connection);
}
static void
complete_pending_call_and_unlock (DBusConnection *connection,
DBusPendingCall *pending,
DBusMessage *message)
{
_dbus_pending_call_set_reply_unlocked (pending, message);
_dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
_dbus_pending_call_start_completion_unlocked(pending);
_dbus_connection_detach_pending_call_and_unlock (connection, pending);
/* Must be called unlocked since it invokes app callback */
_dbus_pending_call_finish_completion (pending);
dbus_pending_call_unref (pending);
}
static dbus_bool_t
check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
DBusPendingCall *pending)
{
DBusMessage *reply;
DBusDispatchStatus status;
reply = check_for_reply_unlocked (connection,
_dbus_pending_call_get_reply_serial_unlocked (pending));
if (reply != NULL)
{
_dbus_verbose ("checked for reply\n");
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
complete_pending_call_and_unlock (connection, pending, reply);
dbus_message_unref (reply);
CONNECTION_LOCK (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
dbus_pending_call_unref (pending);
return TRUE;
}
return FALSE;
}
void
_dbus_connection_block_pending_call (DBusPendingCall *pending)
{
dbus_int64_t start_tv_sec;
long start_tv_usec;
dbus_int64_t tv_sec;
long tv_usec;
DBusDispatchStatus status;
DBusConnection *connection;
dbus_uint32_t client_serial;
DBusTimeout *timeout;
int timeout_milliseconds, elapsed_milliseconds;
_dbus_assert (pending != NULL);
if (dbus_pending_call_get_completed (pending))
return;
dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
connection = _dbus_pending_call_get_connection_and_lock (pending);
/* Flush message queue - note, can affect dispatch status */
_dbus_connection_flush_unlocked (connection);
client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
/* note that timeout_milliseconds is limited to a smallish value
* in _dbus_pending_call_new() so overflows aren't possible
* below
*/
timeout = _dbus_pending_call_get_timeout_unlocked (pending);
_dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
if (timeout)
{
timeout_milliseconds = dbus_timeout_get_interval (timeout);
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %" DBUS_INT64_MODIFIER "d sec %ld usec\n",
timeout_milliseconds,
client_serial,
start_tv_sec, start_tv_usec);
}
else
{
timeout_milliseconds = -1;
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
}
/* check to see if we already got the data off the socket */
/* from another blocked pending call */
if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
return;
/* Now we wait... */
/* always block at least once as we know we don't have the reply yet */
_dbus_connection_do_iteration_unlocked (connection,
pending,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_BLOCK,
timeout_milliseconds);
recheck_status:
_dbus_verbose ("top of recheck\n");
HAVE_LOCK_CHECK (connection);
/* queue messages and get status */
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* the get_completed() is in case a dispatch() while we were blocking
* got the reply instead of us.
*/
if (_dbus_pending_call_get_completed_unlocked (pending))
{
_dbus_verbose ("Pending call completed by dispatch\n");
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
dbus_pending_call_unref (pending);
return;
}
if (status == DBUS_DISPATCH_DATA_REMAINS)
{
if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
return;
}
_dbus_get_monotonic_time (&tv_sec, &tv_usec);
elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
(tv_usec - start_tv_usec) / 1000;
if (!_dbus_connection_get_is_connected_unlocked (connection))
{
DBusMessage *error_msg;
error_msg = generate_local_error_message (client_serial,
DBUS_ERROR_DISCONNECTED,
"Connection was disconnected before a reply was received");
/* on OOM error_msg is set to NULL */
complete_pending_call_and_unlock (connection, pending, error_msg);
if (error_msg != NULL)
dbus_message_unref (error_msg);
dbus_pending_call_unref (pending);
return;
}
else if (connection->disconnect_message_link == NULL)
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
else if (timeout == NULL)
{
if (status == DBUS_DISPATCH_NEED_MEMORY)
{
/* Try sleeping a bit, as we aren't sure we need to block for reading,
* we may already have a reply in the buffer and just can't process
* it.
*/
_dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
_dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
}
else
{
/* block again, we don't have the reply buffered yet. */
_dbus_connection_do_iteration_unlocked (connection,
pending,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_BLOCK,
timeout_milliseconds - elapsed_milliseconds);
}
goto recheck_status;
}
else if (tv_sec < start_tv_sec)
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
else if (elapsed_milliseconds < timeout_milliseconds)
{
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
if (status == DBUS_DISPATCH_NEED_MEMORY)
{
/* Try sleeping a bit, as we aren't sure we need to block for reading,
* we may already have a reply in the buffer and just can't process
* it.
*/
_dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
_dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
}
else
{
/* block again, we don't have the reply buffered yet. */
_dbus_connection_do_iteration_unlocked (connection,
pending,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_BLOCK,
timeout_milliseconds - elapsed_milliseconds);
}
goto recheck_status;
}
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
elapsed_milliseconds);
_dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
/* unlock and call user code */
complete_pending_call_and_unlock (connection, pending, NULL);
/* update user code on dispatch status */
CONNECTION_LOCK (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
dbus_pending_call_unref (pending);
}
int
_dbus_connection_get_pending_fds_count (DBusConnection *connection)
{
return _dbus_transport_get_pending_fds_count (connection->transport);
}
void
_dbus_connection_set_pending_fds_function (DBusConnection *connection,
DBusPendingFdsChangeFunction callback,
void *data)
{
_dbus_transport_set_pending_fds_function (connection->transport,
callback, data);
}
DBusConnection*
dbus_connection_open (const char *address,
DBusError *error)
{
DBusConnection *connection;
_dbus_return_val_if_fail (address != NULL, NULL);
_dbus_return_val_if_error_is_set (error, NULL);
connection = _dbus_connection_open_internal (address,
TRUE,
error);
return connection;
}
DBusConnection*
dbus_connection_open_private (const char *address,
DBusError *error)
{
DBusConnection *connection;
_dbus_return_val_if_fail (address != NULL, NULL);
_dbus_return_val_if_error_is_set (error, NULL);
connection = _dbus_connection_open_internal (address,
FALSE,
error);
return connection;
}
DBusConnection *
dbus_connection_ref (DBusConnection *connection)
{
dbus_int32_t old_refcount;
_dbus_return_val_if_fail (connection != NULL, NULL);
_dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
old_refcount = _dbus_atomic_inc (&connection->refcount);
_dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
"ref");
return connection;
}
static void
free_outgoing_message (void *element,
void *data)
{
DBusMessage *message = element;
DBusConnection *connection = data;
_dbus_message_remove_counter (message, connection->outgoing_counter);
dbus_message_unref (message);
}
/* This is run without the mutex held, but after the last reference
* to the connection has been dropped we should have no thread-related
* problems
*/
static void
_dbus_connection_last_unref (DBusConnection *connection)
{
DBusList *link;
_dbus_verbose ("Finalizing connection %p\n", connection);
_dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
/* You have to disconnect the connection before unref:ing it. Otherwise
* you won't get the disconnected message.
*/
_dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
_dbus_assert (connection->server_guid == NULL);
/* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
_dbus_object_tree_free_all_unlocked (connection->objects);
dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
dbus_connection_set_windows_user_function (connection, NULL, NULL, NULL);
_dbus_watch_list_free (connection->watches);
connection->watches = NULL;
_dbus_timeout_list_free (connection->timeouts);
connection->timeouts = NULL;
_dbus_data_slot_list_free (&connection->slot_list);
link = _dbus_list_get_first_link (&connection->filter_list);
while (link != NULL)
{
DBusMessageFilter *filter = link->data;
DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
filter->function = NULL;
_dbus_message_filter_unref (filter); /* calls app callback */
link->data = NULL;
link = next;
}
_dbus_list_clear (&connection->filter_list);
/* ---- Done with stuff that invokes application callbacks */
_dbus_object_tree_unref (connection->objects);
_dbus_hash_table_unref (connection->pending_replies);
connection->pending_replies = NULL;
_dbus_list_foreach (&connection->outgoing_messages,
free_outgoing_message,
connection);
_dbus_list_clear (&connection->outgoing_messages);
_dbus_list_clear_full (&connection->incoming_messages,
(DBusFreeFunction) dbus_message_unref);
_dbus_counter_unref (connection->outgoing_counter);
_dbus_transport_unref (connection->transport);
if (connection->disconnect_message_link)
{
DBusMessage *message = connection->disconnect_message_link->data;
dbus_message_unref (message);
_dbus_list_free_link (connection->disconnect_message_link);
}
_dbus_condvar_free_at_location (&connection->dispatch_cond);
_dbus_condvar_free_at_location (&connection->io_path_cond);
_dbus_cmutex_free_at_location (&connection->io_path_mutex);
_dbus_cmutex_free_at_location (&connection->dispatch_mutex);
_dbus_rmutex_free_at_location (&connection->slot_mutex);
_dbus_rmutex_free_at_location (&connection->mutex);
dbus_free (connection);
}
void
dbus_connection_unref (DBusConnection *connection)
{
dbus_int32_t old_refcount;
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (connection->generation == _dbus_current_generation);
old_refcount = _dbus_atomic_dec (&connection->refcount);
_dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
"unref");
if (old_refcount == 1)
{
#ifndef DBUS_DISABLE_CHECKS
if (_dbus_transport_get_is_connected (connection->transport))
{
_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",
connection->shareable ?
"Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
"Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
return;
}
#endif
_dbus_connection_last_unref (connection);
}
}
/*
* Note that the transport can disconnect itself (other end drops us)
* and in that case this function never runs. So this function must
* not do anything more than disconnect the transport and update the
* dispatch status.
*
* If the transport self-disconnects, then we assume someone will
* dispatch the connection to cause the dispatch status update.
*/
static void
_dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
{
DBusDispatchStatus status;
HAVE_LOCK_CHECK (connection);
_dbus_verbose ("Disconnecting %p\n", connection);
/* We need to ref because update_dispatch_status_and_unlock will unref
* the connection if it was shared and libdbus was the only remaining
* refcount holder.
*/
_dbus_connection_ref_unlocked (connection);
_dbus_transport_disconnect (connection->transport);
/* This has the side effect of queuing the disconnect message link
* (unless we don't have enough memory, possibly, so don't assert it).
* After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
* should never again return the newly-disconnected connection.
*
* However, we only unref the shared connection and exit_on_disconnect when
* the disconnect message reaches the head of the message queue,
* NOT when it's first queued.
*/
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* This calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
/* Could also call out to user code */
dbus_connection_unref (connection);
}
void
dbus_connection_close (DBusConnection *connection)
{
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (connection->generation == _dbus_current_generation);
CONNECTION_LOCK (connection);
#ifndef DBUS_DISABLE_CHECKS
if (connection->shareable)
{
CONNECTION_UNLOCK (connection);
_dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
return;
}
#endif
_dbus_connection_close_possibly_shared_and_unlock (connection);
}
static dbus_bool_t
_dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
return _dbus_transport_get_is_connected (connection->transport);
}
dbus_bool_t
dbus_connection_get_is_connected (DBusConnection *connection)
{
dbus_bool_t res;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
res = _dbus_connection_get_is_connected_unlocked (connection);
CONNECTION_UNLOCK (connection);
return res;
}
dbus_bool_t
dbus_connection_get_is_authenticated (DBusConnection *connection)
{
dbus_bool_t res;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
res = _dbus_transport_try_to_authenticate (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
dbus_bool_t
dbus_connection_get_is_anonymous (DBusConnection *connection)
{
dbus_bool_t res;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
res = _dbus_transport_get_is_anonymous (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
char*
dbus_connection_get_server_id (DBusConnection *connection)
{
char *id;
_dbus_return_val_if_fail (connection != NULL, NULL);
CONNECTION_LOCK (connection);
id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
CONNECTION_UNLOCK (connection);
return id;
}
dbus_bool_t
dbus_connection_can_send_type(DBusConnection *connection,
int type)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
if (!dbus_type_is_valid (type))
return FALSE;
if (type != DBUS_TYPE_UNIX_FD)
return TRUE;
#ifdef HAVE_UNIX_FD_PASSING
{
dbus_bool_t b;
CONNECTION_LOCK(connection);
b = _dbus_transport_can_pass_unix_fd(connection->transport);
CONNECTION_UNLOCK(connection);
return b;
}
#endif
return FALSE;
}
void
dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
dbus_bool_t exit_on_disconnect)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
connection->exit_on_disconnect = exit_on_disconnect != FALSE;
CONNECTION_UNLOCK (connection);
}
DBusPreallocatedSend*
dbus_connection_preallocate_send (DBusConnection *connection)
{
DBusPreallocatedSend *preallocated;
_dbus_return_val_if_fail (connection != NULL, NULL);
CONNECTION_LOCK (connection);
preallocated =
_dbus_connection_preallocate_send_unlocked (connection);
CONNECTION_UNLOCK (connection);
return preallocated;
}
void
dbus_connection_free_preallocated_send (DBusConnection *connection,
DBusPreallocatedSend *preallocated)
{
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (preallocated != NULL);
_dbus_return_if_fail (connection == preallocated->connection);
_dbus_list_free_link (preallocated->queue_link);
_dbus_counter_unref (preallocated->counter_link->data);
_dbus_list_free_link (preallocated->counter_link);
dbus_free (preallocated);
}
void
dbus_connection_send_preallocated (DBusConnection *connection,
DBusPreallocatedSend *preallocated,
DBusMessage *message,
dbus_uint32_t *client_serial)
{
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (preallocated != NULL);
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (preallocated->connection == connection);
_dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
dbus_message_get_member (message) != NULL);
_dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
(dbus_message_get_interface (message) != NULL &&
dbus_message_get_member (message) != NULL));
CONNECTION_LOCK (connection);
#ifdef HAVE_UNIX_FD_PASSING
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
message->n_unix_fds > 0)
{
/* Refuse to send fds on a connection that cannot handle
them. Unfortunately we cannot return a proper error here, so
the best we can is just return. */
CONNECTION_UNLOCK (connection);
return;
}
#endif
_dbus_connection_send_preallocated_and_unlock (connection,
preallocated,
message, client_serial);
}
static dbus_bool_t
_dbus_connection_send_unlocked_no_update (DBusConnection *connection,
DBusMessage *message,
dbus_uint32_t *client_serial)
{
DBusPreallocatedSend *preallocated;
_dbus_assert (connection != NULL);
_dbus_assert (message != NULL);
preallocated = _dbus_connection_preallocate_send_unlocked (connection);
if (preallocated == NULL)
return FALSE;
_dbus_connection_send_preallocated_unlocked_no_update (connection,
preallocated,
message,
client_serial);
return TRUE;
}
dbus_bool_t
dbus_connection_send (DBusConnection *connection,
DBusMessage *message,
dbus_uint32_t *serial)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (message != NULL, FALSE);
CONNECTION_LOCK (connection);
#ifdef HAVE_UNIX_FD_PASSING
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
message->n_unix_fds > 0)
{
/* Refuse to send fds on a connection that cannot handle
them. Unfortunately we cannot return a proper error here, so
the best we can is just return. */
CONNECTION_UNLOCK (connection);
return FALSE;
}
#endif
return _dbus_connection_send_and_unlock (connection,
message,
serial);
}
static dbus_bool_t
reply_handler_timeout (void *data)
{
DBusConnection *connection;
DBusDispatchStatus status;
DBusPendingCall *pending = data;
connection = _dbus_pending_call_get_connection_and_lock (pending);
_dbus_connection_ref_unlocked (connection);
_dbus_pending_call_queue_timeout_error_unlocked (pending,
connection);
_dbus_connection_remove_timeout_unlocked (connection,
_dbus_pending_call_get_timeout_unlocked (pending));
_dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
_dbus_verbose ("middle\n");
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* Unlocks, and calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
dbus_connection_unref (connection);
return TRUE;
}
dbus_bool_t
dbus_connection_send_with_reply (DBusConnection *connection,
DBusMessage *message,
DBusPendingCall **pending_return,
int timeout_milliseconds)
{
DBusPendingCall *pending;
dbus_int32_t serial = -1;
DBusDispatchStatus status;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
if (pending_return)
*pending_return = NULL;
CONNECTION_LOCK (connection);
#ifdef HAVE_UNIX_FD_PASSING
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
message->n_unix_fds > 0)
{
/* Refuse to send fds on a connection that cannot handle
them. Unfortunately we cannot return a proper error here, so
the best we can do is return TRUE but leave *pending_return
as NULL. */
CONNECTION_UNLOCK (connection);
return TRUE;
}
#endif
if (!_dbus_connection_get_is_connected_unlocked (connection))
{
CONNECTION_UNLOCK (connection);
return TRUE;
}
pending = _dbus_pending_call_new_unlocked (connection,
timeout_milliseconds,
reply_handler_timeout);
if (pending == NULL)
{
CONNECTION_UNLOCK (connection);
return FALSE;
}
/* Assign a serial to the message */
serial = dbus_message_get_serial (message);
if (serial == 0)
{
serial = _dbus_connection_get_next_client_serial (connection);
dbus_message_set_serial (message, serial);
}
if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
goto error;
/* Insert the serial in the pending replies hash;
* hash takes a refcount on DBusPendingCall.
* Also, add the timeout.
*/
if (!_dbus_connection_attach_pending_call_unlocked (connection,
pending))
goto error;
if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
{
_dbus_connection_detach_pending_call_and_unlock (connection,
pending);
goto error_unlocked;
}
if (pending_return)
*pending_return = pending; /* hand off refcount */
else
{
_dbus_connection_detach_pending_call_unlocked (connection, pending);
/* we still have a ref to the pending call in this case, we unref
* after unlocking, below
*/
}
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* this calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
if (pending_return == NULL)
dbus_pending_call_unref (pending);
return TRUE;
error:
CONNECTION_UNLOCK (connection);
error_unlocked:
dbus_pending_call_unref (pending);
return FALSE;
}
DBusMessage*
dbus_connection_send_with_reply_and_block (DBusConnection *connection,
DBusMessage *message,
int timeout_milliseconds,
DBusError *error)
{
DBusMessage *reply;
DBusPendingCall *pending;
_dbus_return_val_if_fail (connection != NULL, NULL);
_dbus_return_val_if_fail (message != NULL, NULL);
_dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
_dbus_return_val_if_error_is_set (error, NULL);
#ifdef HAVE_UNIX_FD_PASSING
CONNECTION_LOCK (connection);
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
message->n_unix_fds > 0)
{
CONNECTION_UNLOCK (connection);
dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
return NULL;
}
CONNECTION_UNLOCK (connection);
#endif
if (!dbus_connection_send_with_reply (connection, message,
&pending, timeout_milliseconds))
{
_DBUS_SET_OOM (error);
return NULL;
}
if (pending == NULL)
{
dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
return NULL;
}
dbus_pending_call_block (pending);
reply = dbus_pending_call_steal_reply (pending);
dbus_pending_call_unref (pending);
/* call_complete_and_unlock() called from pending_call_block() should
* always fill this in.
*/
_dbus_assert (reply != NULL);
if (dbus_set_error_from_message (error, reply))
{
dbus_message_unref (reply);
return NULL;
}
else
return reply;
}
static DBusDispatchStatus
_dbus_connection_flush_unlocked (DBusConnection *connection)
{
/* We have to specify DBUS_ITERATION_DO_READING here because
* otherwise we could have two apps deadlock if they are both doing
* a flush(), and the kernel buffers fill up. This could change the
* dispatch status.
*/
DBusDispatchStatus status;
HAVE_LOCK_CHECK (connection);
while (connection->n_outgoing > 0 &&
_dbus_connection_get_is_connected_unlocked (connection))
{
_dbus_verbose ("doing iteration in\n");
HAVE_LOCK_CHECK (connection);
_dbus_connection_do_iteration_unlocked (connection,
NULL,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_DO_WRITING |
DBUS_ITERATION_BLOCK,
-1);
}
HAVE_LOCK_CHECK (connection);
_dbus_verbose ("middle\n");
status = _dbus_connection_get_dispatch_status_unlocked (connection);
HAVE_LOCK_CHECK (connection);
return status;
}
void
dbus_connection_flush (DBusConnection *connection)
{
/* We have to specify DBUS_ITERATION_DO_READING here because
* otherwise we could have two apps deadlock if they are both doing
* a flush(), and the kernel buffers fill up. This could change the
* dispatch status.
*/
DBusDispatchStatus status;
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
status = _dbus_connection_flush_unlocked (connection);
HAVE_LOCK_CHECK (connection);
/* Unlocks and calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
_dbus_verbose ("end\n");
}
static dbus_bool_t
_dbus_connection_read_write_dispatch (DBusConnection *connection,
int timeout_milliseconds,
dbus_bool_t dispatch)
{
DBusDispatchStatus dstatus;
dbus_bool_t progress_possible;
/* Need to grab a ref here in case we're a private connection and
* the user drops the last ref in a handler we call; see bug
* https://bugs.freedesktop.org/show_bug.cgi?id=15635
*/
dbus_connection_ref (connection);
dstatus = dbus_connection_get_dispatch_status (connection);
if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
{
_dbus_verbose ("doing dispatch\n");
dbus_connection_dispatch (connection);
CONNECTION_LOCK (connection);
}
else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
{
_dbus_verbose ("pausing for memory\n");
_dbus_memory_pause_based_on_timeout (timeout_milliseconds);
CONNECTION_LOCK (connection);
}
else
{
CONNECTION_LOCK (connection);
if (_dbus_connection_get_is_connected_unlocked (connection))
{
_dbus_verbose ("doing iteration\n");
_dbus_connection_do_iteration_unlocked (connection,
NULL,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_DO_WRITING |
DBUS_ITERATION_BLOCK,
timeout_milliseconds);
}
}
HAVE_LOCK_CHECK (connection);
/* If we can dispatch, we can make progress until the Disconnected message
* has been processed; if we can only read/write, we can make progress
* as long as the transport is open.
*/
if (dispatch)
progress_possible = connection->n_incoming != 0 ||
connection->disconnect_message_link != NULL;
else
progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
CONNECTION_UNLOCK (connection);
dbus_connection_unref (connection);
return progress_possible; /* TRUE if we can make more progress */
}
dbus_bool_t
dbus_connection_read_write_dispatch (DBusConnection *connection,
int timeout_milliseconds)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
}
dbus_bool_t
dbus_connection_read_write (DBusConnection *connection,
int timeout_milliseconds)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
}
/* We need to call this anytime we pop the head of the queue, and then
* update_dispatch_status_and_unlock needs to be called afterward
* which will "process" the disconnected message and set
* disconnected_message_processed.
*/
static void
check_disconnected_message_arrived_unlocked (DBusConnection *connection,
DBusMessage *head_of_queue)
{
HAVE_LOCK_CHECK (connection);
/* checking that the link is NULL is an optimization to avoid the is_signal call */
if (connection->disconnect_message_link == NULL &&
dbus_message_is_signal (head_of_queue,
DBUS_INTERFACE_LOCAL,
"Disconnected"))
{
connection->disconnected_message_arrived = TRUE;
}
}
DBusMessage*
dbus_connection_borrow_message (DBusConnection *connection)
{
DBusDispatchStatus status;
DBusMessage *message;
_dbus_return_val_if_fail (connection != NULL, NULL);
_dbus_verbose ("start\n");
/* this is called for the side effect that it queues
* up any messages from the transport
*/
status = dbus_connection_get_dispatch_status (connection);
if (status != DBUS_DISPATCH_DATA_REMAINS)
return NULL;
CONNECTION_LOCK (connection);
_dbus_connection_acquire_dispatch (connection);
/* While a message is outstanding, the dispatch lock is held */
_dbus_assert (connection->message_borrowed == NULL);
connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
message = connection->message_borrowed;
check_disconnected_message_arrived_unlocked (connection, message);
/* Note that we KEEP the dispatch lock until the message is returned */
if (message == NULL)
_dbus_connection_release_dispatch (connection);
CONNECTION_UNLOCK (connection);
_dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
/* We don't update dispatch status until it's returned or stolen */
return message;
}
void
dbus_connection_return_message (DBusConnection *connection,
DBusMessage *message)
{
DBusDispatchStatus status;
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (message == connection->message_borrowed);
_dbus_return_if_fail (connection->dispatch_acquired);
CONNECTION_LOCK (connection);
_dbus_assert (message == connection->message_borrowed);
connection->message_borrowed = NULL;
_dbus_connection_release_dispatch (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
_dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
}
void
dbus_connection_steal_borrowed_message (DBusConnection *connection,
DBusMessage *message)
{
DBusMessage *pop_message;
DBusDispatchStatus status;
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (message == connection->message_borrowed);
_dbus_return_if_fail (connection->dispatch_acquired);
CONNECTION_LOCK (connection);
_dbus_assert (message == connection->message_borrowed);
pop_message = _dbus_list_pop_first (&connection->incoming_messages);
_dbus_assert (message == pop_message);
(void) pop_message; /* unused unless asserting */
connection->n_incoming -= 1;
_dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
message, connection->n_incoming);
connection->message_borrowed = NULL;
_dbus_connection_release_dispatch (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
_dbus_message_trace_ref (message, -1, -1,
"dbus_connection_steal_borrowed_message");
}
/* See dbus_connection_pop_message, but requires the caller to own
* the lock before calling. May drop the lock while running.
*/
static DBusList*
_dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
_dbus_assert (connection->message_borrowed == NULL);
if (connection->n_incoming > 0)
{
DBusList *link;
link = _dbus_list_pop_first_link (&connection->incoming_messages);
connection->n_incoming -= 1;
_dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
link->data,
dbus_message_type_to_string (dbus_message_get_type (link->data)),
dbus_message_get_path (link->data) ?
dbus_message_get_path (link->data) :
"no path",
dbus_message_get_interface (link->data) ?
dbus_message_get_interface (link->data) :
"no interface",
dbus_message_get_member (link->data) ?
dbus_message_get_member (link->data) :
"no member",
dbus_message_get_signature (link->data),
dbus_message_get_serial (link->data),
connection, connection->n_incoming);
_dbus_message_trace_ref (link->data, -1, -1,
"_dbus_connection_pop_message_link_unlocked");
check_disconnected_message_arrived_unlocked (connection, link->data);
return link;
}
else
return NULL;
}
/* See dbus_connection_pop_message, but requires the caller to own
* the lock before calling. May drop the lock while running.
*/
static DBusMessage*
_dbus_connection_pop_message_unlocked (DBusConnection *connection)
{
DBusList *link;
HAVE_LOCK_CHECK (connection);
link = _dbus_connection_pop_message_link_unlocked (connection);
if (link != NULL)
{
DBusMessage *message;
message = link->data;
_dbus_list_free_link (link);
return message;
}
else
return NULL;
}
static void
_dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
DBusList *message_link)
{
HAVE_LOCK_CHECK (connection);
_dbus_assert (message_link != NULL);
/* You can't borrow a message while a link is outstanding */
_dbus_assert (connection->message_borrowed == NULL);
/* We had to have the dispatch lock across the pop/putback */
_dbus_assert (connection->dispatch_acquired);
_dbus_list_prepend_link (&connection->incoming_messages,
message_link);
connection->n_incoming += 1;
_dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
message_link->data,
dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
dbus_message_get_interface (message_link->data) ?
dbus_message_get_interface (message_link->data) :
"no interface",
dbus_message_get_member (message_link->data) ?
dbus_message_get_member (message_link->data) :
"no member",
dbus_message_get_signature (message_link->data),
connection, connection->n_incoming);
_dbus_message_trace_ref (message_link->data, -1, -1,
"_dbus_connection_putback_message_link_unlocked");
}
DBusMessage*
dbus_connection_pop_message (DBusConnection *connection)
{
DBusMessage *message;
DBusDispatchStatus status;
_dbus_verbose ("start\n");
/* this is called for the side effect that it queues
* up any messages from the transport
*/
status = dbus_connection_get_dispatch_status (connection);
if (status != DBUS_DISPATCH_DATA_REMAINS)
return NULL;
CONNECTION_LOCK (connection);
_dbus_connection_acquire_dispatch (connection);
HAVE_LOCK_CHECK (connection);
message = _dbus_connection_pop_message_unlocked (connection);
_dbus_verbose ("Returning popped message %p\n", message);
_dbus_connection_release_dispatch (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
return message;
}
static void
_dbus_connection_acquire_dispatch (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
_dbus_connection_ref_unlocked (connection);
CONNECTION_UNLOCK (connection);
_dbus_verbose ("locking dispatch_mutex\n");
_dbus_cmutex_lock (connection->dispatch_mutex);
while (connection->dispatch_acquired)
{
_dbus_verbose ("waiting for dispatch to be acquirable\n");
_dbus_condvar_wait (connection->dispatch_cond,
connection->dispatch_mutex);
}
_dbus_assert (!connection->dispatch_acquired);
connection->dispatch_acquired = TRUE;
_dbus_verbose ("unlocking dispatch_mutex\n");
_dbus_cmutex_unlock (connection->dispatch_mutex);
CONNECTION_LOCK (connection);
_dbus_connection_unref_unlocked (connection);
}
static void
_dbus_connection_release_dispatch (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
_dbus_verbose ("locking dispatch_mutex\n");
_dbus_cmutex_lock (connection->dispatch_mutex);
_dbus_assert (connection->dispatch_acquired);
connection->dispatch_acquired = FALSE;
_dbus_condvar_wake_one (connection->dispatch_cond);
_dbus_verbose ("unlocking dispatch_mutex\n");
_dbus_cmutex_unlock (connection->dispatch_mutex);
}
static void
_dbus_connection_failed_pop (DBusConnection *connection,
DBusList *message_link)
{
_dbus_list_prepend_link (&connection->incoming_messages,
message_link);
connection->n_incoming += 1;
}
/* Note this may be called multiple times since we don't track whether we already did it */
static void
notify_disconnected_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
/* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
* connection from dbus_bus_get(). We make the same guarantee for
* dbus_connection_open() but in a different way since we don't want to
* unref right here; we instead check for connectedness before returning
* the connection from the hash.
*/
_dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
/* Dump the outgoing queue, we aren't going to be able to
* send it now, and we'd like accessors like
* dbus_connection_get_outgoing_size() to be accurate.
*/
if (connection->n_outgoing > 0)
{
DBusList *link;
_dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
connection->n_outgoing);
while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
{
_dbus_connection_message_sent_unlocked (connection, link->data);
}
}
}
/* Note this may be called multiple times since we don't track whether we already did it */
static DBusDispatchStatus
notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
if (connection->disconnect_message_link != NULL)
{
_dbus_verbose ("Sending disconnect message\n");
/* If we have pending calls, queue their timeouts - we want the Disconnected
* to be the last message, after these timeouts.
*/
connection_timeout_and_complete_all_pending_calls_unlocked (connection);
/* We haven't sent the disconnect message already,
* and all real messages have been queued up.
*/
_dbus_connection_queue_synthesized_message_link (connection,
connection->disconnect_message_link);
connection->disconnect_message_link = NULL;
return DBUS_DISPATCH_DATA_REMAINS;
}
return DBUS_DISPATCH_COMPLETE;
}
static DBusDispatchStatus
_dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
{
HAVE_LOCK_CHECK (connection);
if (connection->n_incoming > 0)
return DBUS_DISPATCH_DATA_REMAINS;
else if (!_dbus_transport_queue_messages (connection->transport))
return DBUS_DISPATCH_NEED_MEMORY;
else
{
DBusDispatchStatus status;
dbus_bool_t is_connected;
status = _dbus_transport_get_dispatch_status (connection->transport);
is_connected = _dbus_transport_get_is_connected (connection->transport);
_dbus_verbose ("dispatch status = %s is_connected = %d\n",
DISPATCH_STATUS_NAME (status), is_connected);
if (!is_connected)
{
/* It's possible this would be better done by having an explicit
* notification from _dbus_transport_disconnect() that would
* synchronously do this, instead of waiting for the next dispatch
* status check. However, probably not good to change until it causes
* a problem.
*/
notify_disconnected_unlocked (connection);
/* I'm not sure this is needed; the idea is that we want to
* queue the Disconnected only after we've read all the
* messages, but if we're disconnected maybe we are guaranteed
* to have read them all ?
*/
if (status == DBUS_DISPATCH_COMPLETE)
status = notify_disconnected_and_dispatch_complete_unlocked (connection);
}
if (status != DBUS_DISPATCH_COMPLETE)
return status;
else if (connection->n_incoming > 0)
return DBUS_DISPATCH_DATA_REMAINS;
else
return DBUS_DISPATCH_COMPLETE;
}
}
static void
_dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
DBusDispatchStatus new_status)
{
dbus_bool_t changed;
DBusDispatchStatusFunction function;
void *data;
HAVE_LOCK_CHECK (connection);
_dbus_connection_ref_unlocked (connection);
changed = new_status != connection->last_dispatch_status;
connection->last_dispatch_status = new_status;
function = connection->dispatch_status_function;
data = connection->dispatch_status_data;
if (connection->disconnected_message_arrived &&
!connection->disconnected_message_processed)
{
connection->disconnected_message_processed = TRUE;
/* this does an unref, but we have a ref
* so we should not run the finalizer here
* inside the lock.
*/
connection_forget_shared_unlocked (connection);
if (connection->exit_on_disconnect)
{
CONNECTION_UNLOCK (connection);
_dbus_verbose ("Exiting on Disconnected signal\n");
_dbus_exit (1);
_dbus_assert_not_reached ("Call to exit() returned");
}
}
/* We drop the lock */
CONNECTION_UNLOCK (connection);
if (changed && function)
{
_dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
connection, new_status,
DISPATCH_STATUS_NAME (new_status));
(* function) (connection, new_status, data);
}
dbus_connection_unref (connection);
}
DBusDispatchStatus
dbus_connection_get_dispatch_status (DBusConnection *connection)
{
DBusDispatchStatus status;
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
_dbus_verbose ("start\n");
CONNECTION_LOCK (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
CONNECTION_UNLOCK (connection);
return status;
}
static DBusHandlerResult
_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
DBusMessage *message)
{
dbus_bool_t sent = FALSE;
DBusMessage *ret = NULL;
DBusList *expire_link;
if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
{
/* This means we're letting the bus route this message */
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
{
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
/* Preallocate a linked-list link, so that if we need to dispose of a
* message, we can attach it to the expired list */
expire_link = _dbus_list_alloc_link (NULL);
if (!expire_link)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
if (dbus_message_is_method_call (message,
DBUS_INTERFACE_PEER,
"Ping"))
{
ret = dbus_message_new_method_return (message);
if (ret == NULL)
goto out;
sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
}
else if (dbus_message_is_method_call (message,
DBUS_INTERFACE_PEER,
"GetMachineId"))
{
DBusString uuid;
DBusError error = DBUS_ERROR_INIT;
if (!_dbus_string_init (&uuid))
goto out;
if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
{
const char *v_STRING;
ret = dbus_message_new_method_return (message);
if (ret == NULL)
{
_dbus_string_free (&uuid);
goto out;
}
v_STRING = _dbus_string_get_const_data (&uuid);
if (dbus_message_append_args (ret,
DBUS_TYPE_STRING, &v_STRING,
DBUS_TYPE_INVALID))
{
sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
}
}
else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
{
dbus_error_free (&error);
goto out;
}
else
{
ret = dbus_message_new_error (message, error.name, error.message);
dbus_error_free (&error);
if (ret == NULL)
goto out;
sent = _dbus_connection_send_unlocked_no_update (connection, ret,
NULL);
}
_dbus_string_free (&uuid);
}
else
{
/* We need to bounce anything else with this interface, otherwise apps
* could start extending the interface and when we added extensions
* here to DBusConnection we'd break those apps.
*/
ret = dbus_message_new_error (message,
DBUS_ERROR_UNKNOWN_METHOD,
"Unknown method invoked on org.freedesktop.DBus.Peer interface");
if (ret == NULL)
goto out;
sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
}
out:
if (ret == NULL)
{
_dbus_list_free_link (expire_link);
}
else
{
/* It'll be safe to unref the reply when we unlock */
expire_link->data = ret;
_dbus_list_prepend_link (&connection->expired_messages, expire_link);
}
if (!sent)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
return DBUS_HANDLER_RESULT_HANDLED;
}
static DBusHandlerResult
_dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
DBusMessage *message)
{
/* We just run one filter for now but have the option to run more
if the spec calls for it in the future */
return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
}
DBusDispatchStatus
dbus_connection_dispatch (DBusConnection *connection)
{
DBusMessage *message;
DBusList *link, *filter_list_copy, *message_link;
DBusHandlerResult result;
DBusPendingCall *pending;
dbus_int32_t reply_serial;
DBusDispatchStatus status;
dbus_bool_t found_object;
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
_dbus_verbose ("\n");
CONNECTION_LOCK (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
if (status != DBUS_DISPATCH_DATA_REMAINS)
{
/* unlocks and calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
return status;
}
/* We need to ref the connection since the callback could potentially
* drop the last ref to it
*/
_dbus_connection_ref_unlocked (connection);
_dbus_connection_acquire_dispatch (connection);
HAVE_LOCK_CHECK (connection);
message_link = _dbus_connection_pop_message_link_unlocked (connection);
if (message_link == NULL)
{
/* another thread dispatched our stuff */
_dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
_dbus_connection_release_dispatch (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
dbus_connection_unref (connection);
return status;
}
message = message_link->data;
_dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
message,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
"no interface",
dbus_message_get_member (message) ?
dbus_message_get_member (message) :
"no member",
dbus_message_get_signature (message));
result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
/* Pending call handling must be first, because if you do
* dbus_connection_send_with_reply_and_block() or
* dbus_pending_call_block() then no handlers/filters will be run on
* the reply. We want consistent semantics in the case where we
* dbus_connection_dispatch() the reply.
*/
reply_serial = dbus_message_get_reply_serial (message);
pending = _dbus_hash_table_lookup_int (connection->pending_replies,
reply_serial);
if (pending)
{
_dbus_verbose ("Dispatching a pending reply\n");
complete_pending_call_and_unlock (connection, pending, message);
pending = NULL; /* it's probably unref'd */
CONNECTION_LOCK (connection);
_dbus_verbose ("pending call completed in dispatch\n");
result = DBUS_HANDLER_RESULT_HANDLED;
goto out;
}
/* If skipping builtin filters, we are probably a monitor. */
if (connection->builtin_filters_enabled)
{
result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
goto out;
}
if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
{
_dbus_connection_release_dispatch (connection);
HAVE_LOCK_CHECK (connection);
_dbus_connection_failed_pop (connection, message_link);
/* unlocks and calls user code */
_dbus_connection_update_dispatch_status_and_unlock (connection,
DBUS_DISPATCH_NEED_MEMORY);
dbus_connection_unref (connection);
return DBUS_DISPATCH_NEED_MEMORY;
}
for (link = _dbus_list_get_first_link (&filter_list_copy);
link != NULL;
link = _dbus_list_get_next_link (&filter_list_copy, link))
_dbus_message_filter_ref (link->data);
/* We're still protected from dispatch() reentrancy here
* since we acquired the dispatcher
*/
CONNECTION_UNLOCK (connection);
link = _dbus_list_get_first_link (&filter_list_copy);
while (link != NULL)
{
DBusMessageFilter *filter = link->data;
DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
if (filter->function == NULL)
{
_dbus_verbose (" filter was removed in a callback function\n");
link = next;
continue;
}
_dbus_verbose (" running filter on message %p\n", message);
result = (* filter->function) (connection, message, filter->user_data);
if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
break;
link = next;
}
_dbus_list_clear_full (&filter_list_copy,
(DBusFreeFunction) _dbus_message_filter_unref);
CONNECTION_LOCK (connection);
if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
{
_dbus_verbose ("No memory\n");
goto out;
}
else if (result == DBUS_HANDLER_RESULT_HANDLED)
{
_dbus_verbose ("filter handled message in dispatch\n");
goto out;
}
/* We're still protected from dispatch() reentrancy here
* since we acquired the dispatcher
*/
_dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
message,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
"no interface",
dbus_message_get_member (message) ?
dbus_message_get_member (message) :
"no member",
dbus_message_get_signature (message));
HAVE_LOCK_CHECK (connection);
result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
message,
&found_object);
CONNECTION_LOCK (connection);
if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
{
_dbus_verbose ("object tree handled message in dispatch\n");
goto out;
}
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
{
DBusMessage *reply;
DBusString str;
DBusPreallocatedSend *preallocated;
DBusList *expire_link;
_dbus_verbose (" sending error %s\n",
DBUS_ERROR_UNKNOWN_METHOD);
if (!_dbus_string_init (&str))
{
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error string in dispatch\n");
goto out;
}
if (!_dbus_string_append_printf (&str,
"Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
dbus_message_get_member (message),
dbus_message_get_signature (message),
dbus_message_get_interface (message)))
{
_dbus_string_free (&str);
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error string in dispatch\n");
goto out;
}
reply = dbus_message_new_error (message,
found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
_dbus_string_get_const_data (&str));
_dbus_string_free (&str);
if (reply == NULL)
{
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error reply in dispatch\n");
goto out;
}
expire_link = _dbus_list_alloc_link (reply);
if (expire_link == NULL)
{
dbus_message_unref (reply);
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error send in dispatch\n");
goto out;
}
preallocated = _dbus_connection_preallocate_send_unlocked (connection);
if (preallocated == NULL)
{
_dbus_list_free_link (expire_link);
/* It's OK that this is finalized, because it hasn't been seen by
* anything that could attach user callbacks */
dbus_message_unref (reply);
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error send in dispatch\n");
goto out;
}
_dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
reply, NULL);
/* reply will be freed when we release the lock */
_dbus_list_prepend_link (&connection->expired_messages, expire_link);
result = DBUS_HANDLER_RESULT_HANDLED;
}
_dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_interface (message) ?
dbus_message_get_interface (message) :
"no interface",
dbus_message_get_member (message) ?
dbus_message_get_member (message) :
"no member",
dbus_message_get_signature (message),
connection);
out:
if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
{
_dbus_verbose ("out of memory\n");
/* Put message back, and we'll start over.
* Yes this means handlers must be idempotent if they
* don't return HANDLED; c'est la vie.
*/
_dbus_connection_putback_message_link_unlocked (connection,
message_link);
/* now we don't want to free them */
message_link = NULL;
message = NULL;
}
else
{
_dbus_verbose (" ... done dispatching\n");
}
_dbus_connection_release_dispatch (connection);
HAVE_LOCK_CHECK (connection);
if (message != NULL)
{
/* We don't want this message to count in maximum message limits when
* computing the dispatch status, below. We have to drop the lock
* temporarily, because finalizing a message can trigger callbacks.
*
* We have a reference to the connection, and we don't use any cached
* pointers to the connection's internals below this point, so it should
* be safe to drop the lock and take it back. */
CONNECTION_UNLOCK (connection);
dbus_message_unref (message);
CONNECTION_LOCK (connection);
}
if (message_link != NULL)
_dbus_list_free_link (message_link);
_dbus_verbose ("before final status update\n");
status = _dbus_connection_get_dispatch_status_unlocked (connection);
/* unlocks and calls user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
dbus_connection_unref (connection);
return status;
}
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)
{
dbus_bool_t retval;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
retval = _dbus_watch_list_set_functions (connection->watches,
add_function, remove_function,
toggled_function,
data, free_data_function);
CONNECTION_UNLOCK (connection);
return retval;
}
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)
{
dbus_bool_t retval;
_dbus_return_val_if_fail (connection != NULL, FALSE);
CONNECTION_LOCK (connection);
retval = _dbus_timeout_list_set_functions (connection->timeouts,
add_function, remove_function,
toggled_function,
data, free_data_function);
CONNECTION_UNLOCK (connection);
return retval;
}
void
dbus_connection_set_wakeup_main_function (DBusConnection *connection,
DBusWakeupMainFunction wakeup_main_function,
void *data,
DBusFreeFunction free_data_function)
{
void *old_data;
DBusFreeFunction old_free_data;
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
old_data = connection->wakeup_main_data;
old_free_data = connection->free_wakeup_main_data;
connection->wakeup_main_function = wakeup_main_function;
connection->wakeup_main_data = data;
connection->free_wakeup_main_data = free_data_function;
CONNECTION_UNLOCK (connection);
/* Callback outside the lock */
if (old_free_data)
(*old_free_data) (old_data);
}
void
dbus_connection_set_dispatch_status_function (DBusConnection *connection,
DBusDispatchStatusFunction function,
void *data,
DBusFreeFunction free_data_function)
{
void *old_data;
DBusFreeFunction old_free_data;
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
old_data = connection->dispatch_status_data;
old_free_data = connection->free_dispatch_status_data;
connection->dispatch_status_function = function;
connection->dispatch_status_data = data;
connection->free_dispatch_status_data = free_data_function;
CONNECTION_UNLOCK (connection);
/* Callback outside the lock */
if (old_free_data)
(*old_free_data) (old_data);
}
dbus_bool_t
dbus_connection_get_unix_fd (DBusConnection *connection,
int *fd)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (connection->transport != NULL, FALSE);
#ifdef DBUS_WIN
/* FIXME do this on a lower level */
return FALSE;
#endif
return dbus_connection_get_socket(connection, fd);
}
dbus_bool_t
dbus_connection_get_socket(DBusConnection *connection,
int *fd)
{
dbus_bool_t retval;
DBusSocket s = DBUS_SOCKET_INIT;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (connection->transport != NULL, FALSE);
CONNECTION_LOCK (connection);
retval = _dbus_transport_get_socket_fd (connection->transport, &s);
if (retval)
{
*fd = _dbus_socket_get_int (s);
}
CONNECTION_UNLOCK (connection);
return retval;
}
dbus_bool_t
dbus_connection_get_unix_user (DBusConnection *connection,
unsigned long *uid)
{
dbus_bool_t result;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (uid != NULL, FALSE);
CONNECTION_LOCK (connection);
if (!_dbus_transport_try_to_authenticate (connection->transport))
result = FALSE;
else
result = _dbus_transport_get_unix_user (connection->transport,
uid);
#ifdef DBUS_WIN
_dbus_assert (!result);
#endif
CONNECTION_UNLOCK (connection);
return result;
}
dbus_bool_t
dbus_connection_get_unix_process_id (DBusConnection *connection,
unsigned long *pid)
{
dbus_bool_t result;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (pid != NULL, FALSE);
CONNECTION_LOCK (connection);
if (!_dbus_transport_try_to_authenticate (connection->transport))
result = FALSE;
else
result = _dbus_transport_get_unix_process_id (connection->transport,
pid);
CONNECTION_UNLOCK (connection);
return result;
}
dbus_bool_t
dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
void **data,
dbus_int32_t *data_size)
{
dbus_bool_t result;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (data != NULL, FALSE);
_dbus_return_val_if_fail (data_size != NULL, FALSE);
CONNECTION_LOCK (connection);
if (!_dbus_transport_try_to_authenticate (connection->transport))
result = FALSE;
else
result = _dbus_transport_get_adt_audit_session_data (connection->transport,
data,
data_size);
CONNECTION_UNLOCK (connection);
return result;
}
void
dbus_connection_set_unix_user_function (DBusConnection *connection,
DBusAllowUnixUserFunction function,
void *data,
DBusFreeFunction free_data_function)
{
void *old_data = NULL;
DBusFreeFunction old_free_function = NULL;
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_unix_user_function (connection->transport,
function, data, free_data_function,
&old_data, &old_free_function);
CONNECTION_UNLOCK (connection);
if (old_free_function != NULL)
(* old_free_function) (old_data);
}
/* Same calling convention as dbus_connection_get_windows_user */
dbus_bool_t
_dbus_connection_get_linux_security_label (DBusConnection *connection,
char **label_p)
{
dbus_bool_t result;
_dbus_assert (connection != NULL);
_dbus_assert (label_p != NULL);
CONNECTION_LOCK (connection);
if (!_dbus_transport_try_to_authenticate (connection->transport))
result = FALSE;
else
result = _dbus_transport_get_linux_security_label (connection->transport,
label_p);
#ifndef __linux__
_dbus_assert (!result);
#endif
CONNECTION_UNLOCK (connection);
return result;
}
DBusCredentials *
_dbus_connection_get_credentials (DBusConnection *connection)
{
DBusCredentials *result;
_dbus_assert (connection != NULL);
CONNECTION_LOCK (connection);
if (!_dbus_transport_try_to_authenticate (connection->transport))
result = NULL;
else
result = _dbus_transport_get_credentials (connection->transport);
CONNECTION_UNLOCK (connection);
return result;
}
dbus_bool_t
dbus_connection_get_windows_user (DBusConnection *connection,
char **windows_sid_p)
{
dbus_bool_t result;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
CONNECTION_LOCK (connection);
if (!_dbus_transport_try_to_authenticate (connection->transport))
result = FALSE;
else
result = _dbus_transport_get_windows_user (connection->transport,
windows_sid_p);
#ifdef DBUS_UNIX
_dbus_assert (!result);
#endif
CONNECTION_UNLOCK (connection);
return result;
}
void
dbus_connection_set_windows_user_function (DBusConnection *connection,
DBusAllowWindowsUserFunction function,
void *data,
DBusFreeFunction free_data_function)
{
void *old_data = NULL;
DBusFreeFunction old_free_function = NULL;
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_windows_user_function (connection->transport,
function, data, free_data_function,
&old_data, &old_free_function);
CONNECTION_UNLOCK (connection);
if (old_free_function != NULL)
(* old_free_function) (old_data);
}
void
dbus_connection_set_allow_anonymous (DBusConnection *connection,
dbus_bool_t value)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_allow_anonymous (connection->transport, value);
CONNECTION_UNLOCK (connection);
}
void
dbus_connection_set_builtin_filters_enabled (DBusConnection *connection,
dbus_bool_t value)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
connection->builtin_filters_enabled = value;
CONNECTION_UNLOCK (connection);
}
void
dbus_connection_set_route_peer_messages (DBusConnection *connection,
dbus_bool_t value)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
connection->route_peer_messages = value;
CONNECTION_UNLOCK (connection);
}
dbus_bool_t
dbus_connection_add_filter (DBusConnection *connection,
DBusHandleMessageFunction function,
void *user_data,
DBusFreeFunction free_data_function)
{
DBusMessageFilter *filter;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (function != NULL, FALSE);
filter = dbus_new0 (DBusMessageFilter, 1);
if (filter == NULL)
return FALSE;
_dbus_atomic_inc (&filter->refcount);
CONNECTION_LOCK (connection);
if (!_dbus_list_append (&connection->filter_list,
filter))
{
_dbus_message_filter_unref (filter);
CONNECTION_UNLOCK (connection);
return FALSE;
}
/* Fill in filter after all memory allocated,
* so we don't run the free_user_data_function
* if the add_filter() fails
*/
filter->function = function;
filter->user_data = user_data;
filter->free_user_data_function = free_data_function;
CONNECTION_UNLOCK (connection);
return TRUE;
}
void
dbus_connection_remove_filter (DBusConnection *connection,
DBusHandleMessageFunction function,
void *user_data)
{
DBusList *link;
DBusMessageFilter *filter;
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (function != NULL);
CONNECTION_LOCK (connection);
filter = NULL;
link = _dbus_list_get_last_link (&connection->filter_list);
while (link != NULL)
{
filter = link->data;
if (filter->function == function &&
filter->user_data == user_data)
{
_dbus_list_remove_link (&connection->filter_list, link);
filter->function = NULL;
break;
}
link = _dbus_list_get_prev_link (&connection->filter_list, link);
filter = NULL;
}
CONNECTION_UNLOCK (connection);
#ifndef DBUS_DISABLE_CHECKS
if (filter == NULL)
{
_dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
function, user_data);
return;
}
#endif
/* Call application code */
if (filter->free_user_data_function)
(* filter->free_user_data_function) (filter->user_data);
filter->free_user_data_function = NULL;
filter->user_data = NULL;
_dbus_message_filter_unref (filter);
}
static dbus_bool_t
_dbus_connection_register_object_path (DBusConnection *connection,
dbus_bool_t fallback,
const char *path,
const DBusObjectPathVTable *vtable,
void *user_data,
DBusError *error)
{
char **decomposed_path;
dbus_bool_t retval;
if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
return FALSE;
CONNECTION_LOCK (connection);
retval = _dbus_object_tree_register (connection->objects,
fallback,
(const char **) decomposed_path, vtable,
user_data, error);
CONNECTION_UNLOCK (connection);
dbus_free_string_array (decomposed_path);
return retval;
}
dbus_bool_t
dbus_connection_try_register_object_path (DBusConnection *connection,
const char *path,
const DBusObjectPathVTable *vtable,
void *user_data,
DBusError *error)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
}
dbus_bool_t
dbus_connection_register_object_path (DBusConnection *connection,
const char *path,
const DBusObjectPathVTable *vtable,
void *user_data)
{
dbus_bool_t retval;
DBusError error = DBUS_ERROR_INIT;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
_dbus_warn ("%s", error.message);
dbus_error_free (&error);
return FALSE;
}
return retval;
}
dbus_bool_t
dbus_connection_try_register_fallback (DBusConnection *connection,
const char *path,
const DBusObjectPathVTable *vtable,
void *user_data,
DBusError *error)
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
}
dbus_bool_t
dbus_connection_register_fallback (DBusConnection *connection,
const char *path,
const DBusObjectPathVTable *vtable,
void *user_data)
{
dbus_bool_t retval;
DBusError error = DBUS_ERROR_INIT;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
_dbus_warn ("%s", error.message);
dbus_error_free (&error);
return FALSE;
}
return retval;
}
dbus_bool_t
dbus_connection_unregister_object_path (DBusConnection *connection,
const char *path)
{
char **decomposed_path;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (path[0] == '/', FALSE);
if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
return FALSE;
CONNECTION_LOCK (connection);
_dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
dbus_free_string_array (decomposed_path);
return TRUE;
}
dbus_bool_t
dbus_connection_get_object_path_data (DBusConnection *connection,
const char *path,
void **data_p)
{
char **decomposed_path;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (data_p != NULL, FALSE);
*data_p = NULL;
if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
return FALSE;
CONNECTION_LOCK (connection);
*data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
CONNECTION_UNLOCK (connection);
dbus_free_string_array (decomposed_path);
return TRUE;
}
dbus_bool_t
dbus_connection_list_registered (DBusConnection *connection,
const char *parent_path,
char ***child_entries)
{
char **decomposed_path;
dbus_bool_t retval;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (parent_path != NULL, FALSE);
_dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
_dbus_return_val_if_fail (child_entries != NULL, FALSE);
if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
return FALSE;
CONNECTION_LOCK (connection);
retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
(const char **) decomposed_path,
child_entries);
dbus_free_string_array (decomposed_path);
return retval;
}
static DBusDataSlotAllocator slot_allocator =
_DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
dbus_bool_t
dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
{
return _dbus_data_slot_allocator_alloc (&slot_allocator,
slot_p);
}
void
dbus_connection_free_data_slot (dbus_int32_t *slot_p)
{
_dbus_return_if_fail (*slot_p >= 0);
_dbus_data_slot_allocator_free (&slot_allocator, slot_p);
}
dbus_bool_t
dbus_connection_set_data (DBusConnection *connection,
dbus_int32_t slot,
void *data,
DBusFreeFunction free_data_func)
{
DBusFreeFunction old_free_func;
void *old_data;
dbus_bool_t retval;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (slot >= 0, FALSE);
SLOTS_LOCK (connection);
retval = _dbus_data_slot_list_set (&slot_allocator,
&connection->slot_list,
slot, data, free_data_func,
&old_free_func, &old_data);
SLOTS_UNLOCK (connection);
if (retval)
{
/* Do the actual free outside the connection lock */
if (old_free_func)
(* old_free_func) (old_data);
}
return retval;
}
void*
dbus_connection_get_data (DBusConnection *connection,
dbus_int32_t slot)
{
void *res;
_dbus_return_val_if_fail (connection != NULL, NULL);
_dbus_return_val_if_fail (slot >= 0, NULL);
SLOTS_LOCK (connection);
res = _dbus_data_slot_list_get (&slot_allocator,
&connection->slot_list,
slot);
SLOTS_UNLOCK (connection);
return res;
}
void
dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
{
if (will_modify_sigpipe)
_dbus_atomic_set_nonzero (&_dbus_modify_sigpipe);
else
_dbus_atomic_set_zero (&_dbus_modify_sigpipe);
}
void
dbus_connection_set_max_message_size (DBusConnection *connection,
long size)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_max_message_size (connection->transport,
size);
CONNECTION_UNLOCK (connection);
}
long
dbus_connection_get_max_message_size (DBusConnection *connection)
{
long res;
_dbus_return_val_if_fail (connection != NULL, 0);
CONNECTION_LOCK (connection);
res = _dbus_transport_get_max_message_size (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
void
dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
long n)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_max_message_unix_fds (connection->transport,
n);
CONNECTION_UNLOCK (connection);
}
long
dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
{
long res;
_dbus_return_val_if_fail (connection != NULL, 0);
CONNECTION_LOCK (connection);
res = _dbus_transport_get_max_message_unix_fds (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
void
dbus_connection_set_max_received_size (DBusConnection *connection,
long size)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_max_received_size (connection->transport,
size);
CONNECTION_UNLOCK (connection);
}
long
dbus_connection_get_max_received_size (DBusConnection *connection)
{
long res;
_dbus_return_val_if_fail (connection != NULL, 0);
CONNECTION_LOCK (connection);
res = _dbus_transport_get_max_received_size (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
void
dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
long n)
{
_dbus_return_if_fail (connection != NULL);
CONNECTION_LOCK (connection);
_dbus_transport_set_max_received_unix_fds (connection->transport,
n);
CONNECTION_UNLOCK (connection);
}
long
dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
{
long res;
_dbus_return_val_if_fail (connection != NULL, 0);
CONNECTION_LOCK (connection);
res = _dbus_transport_get_max_received_unix_fds (connection->transport);
CONNECTION_UNLOCK (connection);
return res;
}
long
dbus_connection_get_outgoing_size (DBusConnection *connection)
{
long res;
_dbus_return_val_if_fail (connection != NULL, 0);
CONNECTION_LOCK (connection);
res = _dbus_counter_get_size_value (connection->outgoing_counter);
CONNECTION_UNLOCK (connection);
return res;
}
#ifdef DBUS_ENABLE_STATS
void
_dbus_connection_get_stats (DBusConnection *connection,
dbus_uint32_t *in_messages,
dbus_uint32_t *in_bytes,
dbus_uint32_t *in_fds,
dbus_uint32_t *in_peak_bytes,
dbus_uint32_t *in_peak_fds,
dbus_uint32_t *out_messages,
dbus_uint32_t *out_bytes,
dbus_uint32_t *out_fds,
dbus_uint32_t *out_peak_bytes,
dbus_uint32_t *out_peak_fds)
{
CONNECTION_LOCK (connection);
if (in_messages != NULL)
*in_messages = connection->n_incoming;
_dbus_transport_get_stats (connection->transport,
in_bytes, in_fds, in_peak_bytes, in_peak_fds);
if (out_messages != NULL)
*out_messages = connection->n_outgoing;
if (out_bytes != NULL)
*out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
if (out_fds != NULL)
*out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
if (out_peak_bytes != NULL)
*out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
if (out_peak_fds != NULL)
*out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
CONNECTION_UNLOCK (connection);
}
#endif /* DBUS_ENABLE_STATS */
long
dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
{
long res;
_dbus_return_val_if_fail (connection != NULL, 0);
CONNECTION_LOCK (connection);
res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
CONNECTION_UNLOCK (connection);
return res;
}
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
const char*
_dbus_connection_get_address (DBusConnection *connection)
{
return _dbus_transport_get_address (connection->transport);
}
#endif
dbus_address_entries_free
void dbus_address_entries_free(DBusAddressEntry **entries)
Frees a NULL-terminated array of address entries.
Definition dbus-address.c:194
dbus_parse_address
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:368
dbus_address_entry_get_value
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:249
_dbus_bus_notify_shared_connection_disconnected_unlocked
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:390
_dbus_connection_handle_watch
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.
Definition dbus-connection.c:1500
_dbus_connection_toggle_timeout_unlocked
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.
Definition dbus-connection.c:909
dbus_connection_has_messages_to_send
dbus_bool_t dbus_connection_has_messages_to_send(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
Definition dbus-connection.c:592
_dbus_connection_do_iteration_unlocked
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 ...
Definition dbus-connection.c:1202
_dbus_connection_send_and_unlock
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,...
Definition dbus-connection.c:2112
_dbus_connection_new_for_transport
DBusConnection * _dbus_connection_new_for_transport(DBusTransport *transport)
Creates a new connection for the given transport.
Definition dbus-connection.c:1253
_dbus_connection_has_messages_to_send_unlocked
dbus_bool_t _dbus_connection_has_messages_to_send_unlocked(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
Definition dbus-connection.c:576
DBusWatchRemoveFunction
void(* DBusWatchRemoveFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
Definition dbus-connection.c:677
_dbus_connection_unlock
void _dbus_connection_unlock(DBusConnection *connection)
Releases the connection lock.
Definition dbus-connection.c:403
_dbus_connection_lock
void _dbus_connection_lock(DBusConnection *connection)
Acquires the connection lock.
Definition dbus-connection.c:392
_dbus_connection_remove_watch_unlocked
void _dbus_connection_remove_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Removes a watch using the connection's DBusRemoveWatchFunction if available.
Definition dbus-connection.c:765
_dbus_connection_add_timeout_unlocked
dbus_bool_t _dbus_connection_add_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Adds a timeout using the connection's DBusAddTimeoutFunction if available.
Definition dbus-connection.c:871
_dbus_connection_toggle_watch_unlocked
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.
Definition dbus-connection.c:785
DBusTimeoutToggleFunction
void(* DBusTimeoutToggleFunction)(DBusTimeoutList *list, DBusTimeout *timeout, dbus_bool_t enabled)
Function to be called in protected_change_timeout() with refcount held.
Definition dbus-connection.c:804
DBusTimeoutRemoveFunction
void(* DBusTimeoutRemoveFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
Definition dbus-connection.c:801
_dbus_connection_add_watch_unlocked
dbus_bool_t _dbus_connection_add_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Adds a watch using the connection's DBusAddWatchFunction if available.
Definition dbus-connection.c:747
_dbus_connection_remove_pending_call
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.
Definition dbus-connection.c:1048
_dbus_connection_close_if_only_one_ref
void _dbus_connection_close_if_only_one_ref(DBusConnection *connection)
Used internally to handle the semantics of dbus_server_set_new_connection_function().
Definition dbus-connection.c:2160
_dbus_connection_unref_unlocked
void _dbus_connection_unref_unlocked(DBusConnection *connection)
Decrements the reference count of a DBusConnection.
Definition dbus-connection.c:1447
_dbus_connection_get_message_to_send
DBusMessage * _dbus_connection_get_message_to_send(DBusConnection *connection)
Gets the next outgoing message.
Definition dbus-connection.c:613
DBusTimeoutAddFunction
dbus_bool_t(* DBusTimeoutAddFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
Definition dbus-connection.c:798
_dbus_connection_message_sent_unlocked
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...
Definition dbus-connection.c:629
_dbus_connection_remove_timeout_unlocked
void _dbus_connection_remove_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Removes a timeout using the connection's DBusRemoveTimeoutFunction if available.
Definition dbus-connection.c:889
_dbus_connection_get_next_client_serial
dbus_uint32_t _dbus_connection_get_next_client_serial(DBusConnection *connection)
Allocate and return the next non-zero serial number for outgoing messages.
Definition dbus-connection.c:1474
DBusWatchToggleFunction
void(* DBusWatchToggleFunction)(DBusWatchList *list, DBusWatch *watch, dbus_bool_t enabled)
Function to be called in protected_change_watch() with refcount held.
Definition dbus-connection.c:680
_dbus_connection_queue_received_message_link
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...
Definition dbus-connection.c:484
_dbus_connection_get_pending_fds_count
int _dbus_connection_get_pending_fds_count(DBusConnection *connection)
Return how many file descriptors are pending in the loader.
Definition dbus-connection.c:2577
_dbus_connection_set_pending_fds_function
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...
Definition dbus-connection.c:2590
DBusWatchAddFunction
dbus_bool_t(* DBusWatchAddFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
Definition dbus-connection.c:674
_dbus_connection_block_pending_call
void _dbus_connection_block_pending_call(DBusPendingCall *pending)
Blocks until a pending call times out or gets a reply.
Definition dbus-connection.c:2394
_dbus_connection_queue_synthesized_message_link
void _dbus_connection_queue_synthesized_message_link(DBusConnection *connection, DBusList *link)
Adds a link + message to the incoming message queue.
Definition dbus-connection.c:549
_dbus_connection_close_possibly_shared
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...
Definition dbus-connection.c:1962
_dbus_connection_ref_unlocked
DBusConnection * _dbus_connection_ref_unlocked(DBusConnection *connection)
Increments the reference count of a DBusConnection.
Definition dbus-connection.c:1424
dbus_connection_return_message
void dbus_connection_return_message(DBusConnection *connection, DBusMessage *message)
Used to return a message after peeking at it using dbus_connection_borrow_message().
Definition dbus-connection.c:3917
DBusWatchToggledFunction
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
Definition dbus-connection.h:100
dbus_connection_get_object_path_data
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...
Definition dbus-connection.c:5968
dbus_connection_set_max_message_size
void dbus_connection_set_max_message_size(DBusConnection *connection, long size)
Specifies the maximum size message this connection is allowed to receive.
Definition dbus-connection.c:6187
dbus_connection_flush
void dbus_connection_flush(DBusConnection *connection)
Blocks until the outgoing message queue is empty.
Definition dbus-connection.c:3657
dbus_connection_get_max_message_unix_fds
long dbus_connection_get_max_message_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_unix_fds().
Definition dbus-connection.c:6244
dbus_connection_set_exit_on_disconnect
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.
Definition dbus-connection.c:3160
dbus_connection_get_socket
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.
Definition dbus-connection.c:5193
dbus_connection_pop_message
DBusMessage * dbus_connection_pop_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, removing it from the queue.
Definition dbus-connection.c:4107
dbus_connection_get_max_received_unix_fds
long dbus_connection_get_max_received_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_unix_fds().
Definition dbus-connection.c:6342
dbus_connection_register_object_path
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.
Definition dbus-connection.c:5829
dbus_connection_close
void dbus_connection_close(DBusConnection *connection)
Closes a private connection, so no further data can be sent or received.
Definition dbus-connection.c:2947
dbus_connection_set_max_message_unix_fds
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.
Definition dbus-connection.c:6226
dbus_connection_set_wakeup_main_function
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.
Definition dbus-connection.c:5072
dbus_connection_get_windows_user
dbus_bool_t dbus_connection_get_windows_user(DBusConnection *connection, char **windows_sid_p)
Gets the Windows user SID of the connection if known.
Definition dbus-connection.c:5452
dbus_connection_get_is_authenticated
dbus_bool_t dbus_connection_get_is_authenticated(DBusConnection *connection)
Gets whether the connection was authenticated.
Definition dbus-connection.c:3010
dbus_connection_send_preallocated
void dbus_connection_send_preallocated(DBusConnection *connection, DBusPreallocatedSend *preallocated, DBusMessage *message, dbus_uint32_t *client_serial)
Sends a message using preallocated resources.
Definition dbus-connection.c:3232
dbus_connection_read_write
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...
Definition dbus-connection.c:3817
dbus_connection_get_max_received_size
long dbus_connection_get_max_received_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_size().
Definition dbus-connection.c:6300
dbus_connection_get_unix_fd
dbus_bool_t dbus_connection_get_unix_fd(DBusConnection *connection, int *fd)
Get the UNIX file descriptor of the connection, if any.
Definition dbus-connection.c:5163
DBusDispatchStatusFunction
void(* DBusDispatchStatusFunction)(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
Called when the return value of dbus_connection_get_dispatch_status() may have changed.
Definition dbus-connection.h:131
dbus_connection_can_send_type
dbus_bool_t dbus_connection_can_send_type(DBusConnection *connection, int type)
Tests whether a certain type can be send via the connection.
Definition dbus-connection.c:3120
dbus_connection_list_registered
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.
Definition dbus-connection.c:6005
dbus_connection_get_data
void * dbus_connection_get_data(DBusConnection *connection, dbus_int32_t slot)
Retrieves data previously set with dbus_connection_set_data().
Definition dbus-connection.c:6144
dbus_connection_open_private
DBusConnection * dbus_connection_open_private(const char *address, DBusError *error)
Opens a new, dedicated connection to a remote address.
Definition dbus-connection.c:2678
dbus_connection_get_outgoing_size
long dbus_connection_get_outgoing_size(DBusConnection *connection)
Gets the approximate size in bytes of all messages in the outgoing message queue.
Definition dbus-connection.c:6365
dbus_connection_set_dispatch_status_function
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.
Definition dbus-connection.c:5118
dbus_connection_read_write_dispatch
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...
Definition dbus-connection.c:3785
DBusHandleMessageFunction
DBusHandlerResult(* DBusHandleMessageFunction)(DBusConnection *connection, DBusMessage *message, void *user_data)
Called when a message needs to be handled.
Definition dbus-connection.h:172
dbus_connection_remove_filter
void dbus_connection_remove_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data)
Removes a previously-added message filter.
Definition dbus-connection.c:5690
dbus_connection_get_is_connected
dbus_bool_t dbus_connection_get_is_connected(DBusConnection *connection)
Gets whether the connection is currently open.
Definition dbus-connection.c:2988
dbus_connection_preallocate_send
DBusPreallocatedSend * dbus_connection_preallocate_send(DBusConnection *connection)
Preallocates resources needed to send a message, allowing the message to be sent without the possibil...
Definition dbus-connection.c:3180
DBusAddWatchFunction
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
Definition dbus-connection.h:94
dbus_connection_unref
void dbus_connection_unref(DBusConnection *connection)
Decrements the reference count of a DBusConnection, and finalizes it if the count reaches zero.
Definition dbus-connection.c:2832
dbus_connection_set_max_received_size
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.
Definition dbus-connection.c:6282
DBusTimeoutToggledFunction
void(* DBusTimeoutToggledFunction)(DBusTimeout *timeout, void *data)
Called when dbus_timeout_get_enabled() may return a different value than it did before.
Definition dbus-connection.h:120
dbus_connection_dispatch
DBusDispatchStatus dbus_connection_dispatch(DBusConnection *connection)
Processes any incoming data.
Definition dbus-connection.c:4591
dbus_connection_unregister_object_path
dbus_bool_t dbus_connection_unregister_object_path(DBusConnection *connection, const char *path)
Unregisters the handler registered with exactly the given path.
Definition dbus-connection.c:5936
dbus_connection_set_unix_user_function
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.
Definition dbus-connection.c:5355
dbus_connection_try_register_object_path
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.
Definition dbus-connection.c:5799
dbus_connection_steal_borrowed_message
void dbus_connection_steal_borrowed_message(DBusConnection *connection, DBusMessage *message)
Used to keep a message after peeking at it using dbus_connection_borrow_message().
Definition dbus-connection.c:3951
dbus_connection_allocate_data_slot
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.
Definition dbus-connection.c:6047
dbus_connection_set_change_sigpipe
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...
Definition dbus-connection.c:6170
dbus_connection_get_max_message_size
long dbus_connection_get_max_message_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_size().
Definition dbus-connection.c:6205
dbus_connection_free_data_slot
void dbus_connection_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for connection data slots.
Definition dbus-connection.c:6065
DBusAddTimeoutFunction
dbus_bool_t(* DBusAddTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus needs a new timeout to be monitored by the main loop.
Definition dbus-connection.h:113
dbus_connection_set_max_received_unix_fds
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...
Definition dbus-connection.c:6324
dbus_connection_set_data
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...
Definition dbus-connection.c:6095
dbus_connection_get_dispatch_status
DBusDispatchStatus dbus_connection_get_dispatch_status(DBusConnection *connection)
Gets the current state of the incoming message queue.
Definition dbus-connection.c:4394
dbus_connection_send_with_reply_and_block
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.
Definition dbus-connection.c:3551
dbus_connection_try_register_fallback
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.
Definition dbus-connection.c:5869
dbus_connection_get_adt_audit_session_data
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.
Definition dbus-connection.c:5309
dbus_connection_borrow_message
DBusMessage * dbus_connection_borrow_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, leaving it in the queue.
Definition dbus-connection.c:3866
dbus_connection_send_with_reply
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 ...
Definition dbus-connection.c:3415
dbus_connection_set_windows_user_function
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.
Definition dbus-connection.c:5499
dbus_connection_get_is_anonymous
dbus_bool_t dbus_connection_get_is_anonymous(DBusConnection *connection)
Gets whether the connection is not authenticated as a specific user.
Definition dbus-connection.c:3044
dbus_connection_set_timeout_functions
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.
Definition dbus-connection.c:5034
DBusRemoveWatchFunction
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
Definition dbus-connection.h:106
DBusAllowUnixUserFunction
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,...
Definition dbus-connection.h:146
DBusDispatchStatus
DBusDispatchStatus
Indicates the status of incoming data on a DBusConnection.
Definition dbus-connection.h:83
dbus_connection_register_fallback
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.
Definition dbus-connection.c:5901
dbus_connection_open
DBusConnection * dbus_connection_open(const char *address, DBusError *error)
Gets a connection to a remote address.
Definition dbus-connection.c:2635
dbus_connection_free_preallocated_send
void dbus_connection_free_preallocated_send(DBusConnection *connection, DBusPreallocatedSend *preallocated)
Frees preallocated message-sending resources from dbus_connection_preallocate_send().
Definition dbus-connection.c:3206
dbus_connection_get_outgoing_unix_fds
long dbus_connection_get_outgoing_unix_fds(DBusConnection *connection)
Gets the approximate number of uni fds of all messages in the outgoing message queue.
Definition dbus-connection.c:6426
DBusWakeupMainFunction
void(* DBusWakeupMainFunction)(void *data)
Called when the main loop's thread should be notified that there's now work to do.
Definition dbus-connection.h:138
dbus_connection_set_allow_anonymous
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 ...
Definition dbus-connection.c:5546
dbus_connection_add_filter
dbus_bool_t dbus_connection_add_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data, DBusFreeFunction free_data_function)
Adds a message filter.
Definition dbus-connection.c:5638
dbus_connection_send
dbus_bool_t dbus_connection_send(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial)
Adds a message to the outgoing message queue.
Definition dbus-connection.c:3317
dbus_connection_ref
DBusConnection * dbus_connection_ref(DBusConnection *connection)
Increments the reference count of a DBusConnection.
Definition dbus-connection.c:2700
dbus_connection_set_builtin_filters_enabled
void dbus_connection_set_builtin_filters_enabled(DBusConnection *connection, dbus_bool_t value)
Enables the builtin filtering of messages.
Definition dbus-connection.c:5578
dbus_connection_get_server_id
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.
Definition dbus-connection.c:3089
DBusAllowWindowsUserFunction
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,...
Definition dbus-connection.h:156
dbus_connection_set_watch_functions
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.
Definition dbus-connection.c:4971
DBusRemoveTimeoutFunction
void(* DBusRemoveTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus no longer needs a timeout to be monitored by the main loop.
Definition dbus-connection.h:126
dbus_connection_get_unix_process_id
dbus_bool_t dbus_connection_get_unix_process_id(DBusConnection *connection, unsigned long *pid)
Gets the process ID of the connection if any.
Definition dbus-connection.c:5276
dbus_connection_get_unix_user
dbus_bool_t dbus_connection_get_unix_user(DBusConnection *connection, unsigned long *uid)
Gets the UNIX user ID of the connection if known.
Definition dbus-connection.c:5240
dbus_connection_set_route_peer_messages
void dbus_connection_set_route_peer_messages(DBusConnection *connection, dbus_bool_t value)
Normally DBusConnection automatically handles all messages to the org.freedesktop....
Definition dbus-connection.c:5606
DBUS_DISPATCH_NEED_MEMORY
@ DBUS_DISPATCH_NEED_MEMORY
More memory is needed to continue.
Definition dbus-connection.h:86
DBUS_DISPATCH_COMPLETE
@ DBUS_DISPATCH_COMPLETE
All currently available data has been processed.
Definition dbus-connection.h:85
DBUS_DISPATCH_DATA_REMAINS
@ DBUS_DISPATCH_DATA_REMAINS
There is more data to potentially convert to messages.
Definition dbus-connection.h:84
_dbus_data_slot_allocator_free
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().
Definition dbus-dataslot.c:157
_dbus_data_slot_list_init
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
Definition dbus-dataslot.c:200
_dbus_data_slot_list_free
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...
Definition dbus-dataslot.c:343
_dbus_data_slot_list_get
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
Definition dbus-dataslot.c:288
_dbus_data_slot_list_set
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...
Definition dbus-dataslot.c:224
_dbus_data_slot_allocator_alloc
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:72
DBUS_ERROR_INIT
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition dbus-errors.h:64
dbus_move_error
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition dbus-errors.c:281
dbus_error_has_name
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:304
dbus_set_error
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:356
dbus_error_free
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:213
_dbus_hash_table_get_n_entries
int _dbus_hash_table_get_n_entries(DBusHashTable *table)
Gets the number of hash entries in a hash table.
Definition dbus-hash.c:1461
_dbus_hash_iter_get_value
void * _dbus_hash_iter_get_value(DBusHashIter *iter)
Gets the value of the current entry.
Definition dbus-hash.c:620
_dbus_hash_table_insert_int
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:1312
_dbus_hash_table_insert_string
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:1278
_dbus_hash_table_unref
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:368
_dbus_hash_iter_next
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:550
_dbus_hash_iter_init
void _dbus_hash_iter_init(DBusHashTable *table, DBusHashIter *iter)
Initializes a hash table iterator.
Definition dbus-hash.c:524
_dbus_hash_table_new
DBusHashTable * _dbus_hash_table_new(DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function)
Constructs a new hash table.
Definition dbus-hash.c:292
_dbus_hash_table_remove_int
dbus_bool_t _dbus_hash_table_remove_int(DBusHashTable *table, int key)
Removes the hash entry for the given key.
Definition dbus-hash.c:1215
_dbus_hash_table_remove_string
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:1187
_dbus_hash_table_lookup_string
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:1113
_dbus_hash_iter_remove_entry
void _dbus_hash_iter_remove_entry(DBusHashIter *iter)
Removes the current entry from the hash table.
Definition dbus-hash.c:599
_dbus_hash_table_lookup_int
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:1138
DBUS_HASH_INT
@ DBUS_HASH_INT
Hash keys are integers.
Definition dbus-hash.h:70
DBUS_HASH_STRING
@ DBUS_HASH_STRING
Hash keys are strings.
Definition dbus-hash.h:69
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition dbus-internals.h:164
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition dbus-internals.h:153
_DBUS_UNLOCK
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
Definition dbus-internals.h:438
_DBUS_LOCK
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
Definition dbus-internals.h:437
_dbus_warn_check_failed
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...
Definition dbus-internals.c:310
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition dbus-internals.c:621
_dbus_get_local_machine_uuid_encoded
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.
Definition dbus-internals.c:983
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition dbus-internals.c:278
_DBUS_LOCK_NAME
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
Definition dbus-internals.h:436
_dbus_list_get_first_link
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition dbus-list.c:597
_dbus_list_copy
dbus_bool_t _dbus_list_copy(DBusList **list, DBusList **dest)
Copies a list.
Definition dbus-list.c:727
_dbus_list_pop_first_link
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition dbus-list.c:658
_dbus_list_get_last
void * _dbus_list_get_last(DBusList **list)
Gets the last data in the list.
Definition dbus-list.c:626
_dbus_list_remove
dbus_bool_t _dbus_list_remove(DBusList **list, void *data)
Removes a value from the list.
Definition dbus-list.c:418
_dbus_list_append_link
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition dbus-list.c:318
_dbus_list_clear_full
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition dbus-list.c:570
_dbus_list_remove_link
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition dbus-list.c:530
_dbus_list_get_first
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition dbus-list.c:642
_dbus_list_get_last_link
DBusList * _dbus_list_get_last_link(DBusList **list)
Gets the last link in the list.
Definition dbus-list.c:610
_dbus_list_unlink
void _dbus_list_unlink(DBusList **list, DBusList *link)
Removes the given link from the list, but doesn't free it.
Definition dbus-list.c:502
_dbus_list_get_prev_link
#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:122
_dbus_list_free_link
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition dbus-list.c:257
_dbus_list_pop_first
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition dbus-list.c:679
_dbus_list_foreach
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition dbus-list.c:789
_dbus_list_clear
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition dbus-list.c:545
_dbus_list_prepend_link
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition dbus-list.c:336
_dbus_list_prepend
dbus_bool_t _dbus_list_prepend(DBusList **list, void *data)
Prepends a value to the list.
Definition dbus-list.c:295
_dbus_list_alloc_link
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition dbus-list.c:245
_dbus_list_append
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition dbus-list.c:273
_dbus_list_get_next_link
#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:121
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:51
TRUE
#define TRUE
Expands to "1".
Definition dbus-macros.h:41
FALSE
#define FALSE
Expands to "0".
Definition dbus-macros.h:44
_dbus_current_generation
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition dbus-memory.c:790
_dbus_register_shutdown_func
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:819
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition dbus-memory.c:710
dbus_new
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition dbus-memory.h:59
DBusFreeFunction
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition dbus-memory.h:65
dbus_new0
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition dbus-memory.h:60
dbus_free_string_array
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition dbus-memory.c:758
dbus_message_set_serial
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition dbus-message.c:301
dbus_message_lock
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition dbus-message.c:431
dbus_message_type_to_string
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).
Definition dbus-message.c:5081
_dbus_message_remove_counter
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:399
_dbus_message_add_counter_link
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:327
dbus_message_has_interface
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *iface)
Checks if the message has an interface.
Definition dbus-message.c:3512
dbus_message_set_no_reply
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,...
Definition dbus-message.c:3247
dbus_message_iter_append_basic
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
Definition dbus-message.c:2771
dbus_message_get_path
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...
Definition dbus-message.c:3359
dbus_message_get_interface
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...
Definition dbus-message.c:3490
dbus_message_new_error
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.
Definition dbus-message.c:1515
dbus_message_get_serial
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
Definition dbus-message.c:1168
dbus_message_get_type
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
Definition dbus-message.c:1767
dbus_message_append_args
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
Definition dbus-message.c:1843
dbus_message_new_signal
DBusMessage * dbus_message_new_signal(const char *path, const char *iface, const char *name)
Constructs a new message representing a signal emission.
Definition dbus-message.c:1469
dbus_message_ref
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
Definition dbus-message.c:1712
dbus_message_set_error_name
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
Definition dbus-message.c:3634
dbus_message_get_reply_serial
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
Definition dbus-message.c:1208
dbus_message_new_method_return
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
Definition dbus-message.c:1418
dbus_message_get_destination
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
Definition dbus-message.c:3713
dbus_message_unref
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0.
Definition dbus-message.c:1735
dbus_message_new
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
Definition dbus-message.c:1334
dbus_set_error_from_message
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
Definition dbus-message.c:4059
dbus_message_is_method_call
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.
Definition dbus-message.c:3865
dbus_message_set_reply_serial
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).
Definition dbus-message.c:1184
dbus_message_is_signal
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.
Definition dbus-message.c:3893
dbus_message_get_signature
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
Definition dbus-message.c:3806
dbus_message_get_member
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
Definition dbus-message.c:3576
dbus_message_iter_init_append
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
Definition dbus-message.c:2533
_dbus_object_tree_free_all_unlocked
void _dbus_object_tree_free_all_unlocked(DBusObjectTree *tree)
Free all the handlers in the tree.
Definition dbus-object-tree.c:723
_dbus_object_tree_unregister_and_unlock
void _dbus_object_tree_unregister_and_unlock(DBusObjectTree *tree, const char **path)
Unregisters an object subtree that was registered with the same path.
Definition dbus-object-tree.c:628
_dbus_object_tree_unref
void _dbus_object_tree_unref(DBusObjectTree *tree)
Decrement the reference count.
Definition dbus-object-tree.c:146
_dbus_object_tree_list_registered_and_unlock
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.
Definition dbus-object-tree.c:1211
_dbus_decompose_path
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
Definition dbus-object-tree.c:1247
_dbus_object_tree_register
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.
Definition dbus-object-tree.c:396
_dbus_object_tree_get_user_data_unlocked
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.
Definition dbus-object-tree.c:1080
_dbus_object_tree_dispatch_and_unlock
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...
Definition dbus-object-tree.c:908
_dbus_object_tree_new
DBusObjectTree * _dbus_object_tree_new(DBusConnection *connection)
Creates a new object tree, representing a mapping from paths to handler vtables.
Definition dbus-object-tree.c:95
_dbus_pending_call_finish_completion
void _dbus_pending_call_finish_completion(DBusPendingCall *pending)
Call the notifier function for the pending call.
Definition dbus-pending-call.c:235
_dbus_pending_call_get_connection_and_lock
DBusConnection * _dbus_pending_call_get_connection_and_lock(DBusPendingCall *pending)
Gets the connection associated with this pending call.
Definition dbus-pending-call.c:352
_dbus_pending_call_ref_unlocked
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.
Definition dbus-pending-call.c:423
_dbus_pending_call_queue_timeout_error_unlocked
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...
Definition dbus-pending-call.c:257
_dbus_pending_call_unref_and_unlock
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.
Definition dbus-pending-call.c:486
_dbus_pending_call_get_completed_unlocked
dbus_bool_t _dbus_pending_call_get_completed_unlocked(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
Definition dbus-pending-call.c:509
_dbus_pending_call_set_reply_unlocked
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,...
Definition dbus-pending-call.c:183
_dbus_pending_call_new_unlocked
DBUS_PRIVATE_EXPORT DBusPendingCall * _dbus_pending_call_new_unlocked(DBusConnection *connection, int timeout_milliseconds, DBusTimeoutHandler timeout_handler)
Creates a new pending reply object.
Definition dbus-pending-call.c:120
_dbus_pending_call_set_timeout_error_unlocked
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.
Definition dbus-pending-call.c:383
CONNECTION_LOCK
#define CONNECTION_LOCK(connection)
Internals of DBusPendingCall.
Definition dbus-pending-call.c:55
CONNECTION_UNLOCK
#define CONNECTION_UNLOCK(connection)
shorter and more visible way to write _dbus_connection_unlock()
Definition dbus-pending-call.c:59
_dbus_pending_call_start_completion_unlocked
void _dbus_pending_call_start_completion_unlocked(DBusPendingCall *pending)
Sets the pending call to completed.
Definition dbus-pending-call.c:218
_dbus_pending_call_is_timeout_added_unlocked
dbus_bool_t _dbus_pending_call_is_timeout_added_unlocked(DBusPendingCall *pending)
Checks to see if a timeout has been added.
Definition dbus-pending-call.c:277
_dbus_pending_call_get_reply_serial_unlocked
dbus_uint32_t _dbus_pending_call_get_reply_serial_unlocked(DBusPendingCall *pending)
Gets the reply's serial number.
Definition dbus-pending-call.c:322
_dbus_pending_call_get_connection_unlocked
DBusConnection * _dbus_pending_call_get_connection_unlocked(DBusPendingCall *pending)
Gets the connection associated with this pending call.
Definition dbus-pending-call.c:367
_dbus_pending_call_get_timeout_unlocked
DBusTimeout * _dbus_pending_call_get_timeout_unlocked(DBusPendingCall *pending)
Retrives the timeout.
Definition dbus-pending-call.c:308
_dbus_pending_call_set_timeout_added_unlocked
void _dbus_pending_call_set_timeout_added_unlocked(DBusPendingCall *pending, dbus_bool_t is_added)
Sets wether the timeout has been added.
Definition dbus-pending-call.c:292
dbus_pending_call_ref
DBusPendingCall * dbus_pending_call_ref(DBusPendingCall *pending)
Increments the reference count on a pending call.
Definition dbus-pending-call.c:606
dbus_pending_call_steal_reply
DBusMessage * dbus_pending_call_steal_reply(DBusPendingCall *pending)
Gets the reply, or returns NULL if none has been received yet.
Definition dbus-pending-call.c:731
dbus_pending_call_block
void dbus_pending_call_block(DBusPendingCall *pending)
Block until the pending call is completed.
Definition dbus-pending-call.c:766
dbus_pending_call_get_completed
dbus_bool_t dbus_pending_call_get_completed(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
Definition dbus-pending-call.c:708
dbus_pending_call_unref
void dbus_pending_call_unref(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0.
Definition dbus-pending-call.c:626
DBUS_MESSAGE_TYPE_METHOD_CALL
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type().
Definition dbus-protocol.h:236
DBUS_MESSAGE_TYPE_ERROR
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type().
Definition dbus-protocol.h:240
DBUS_ERROR_UNKNOWN_METHOD
#define DBUS_ERROR_UNKNOWN_METHOD
Method name you invoked isn't known by the object you invoked it on.
Definition dbus-protocol.h:403
DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
Definition dbus-protocol.h:116
DBUS_ERROR_OBJECT_PATH_IN_USE
#define DBUS_ERROR_OBJECT_PATH_IN_USE
There's already an object with the requested object path.
Definition dbus-protocol.h:456
DBUS_MESSAGE_TYPE_SIGNAL
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type().
Definition dbus-protocol.h:242
DBUS_TYPE_STRING
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
Definition dbus-protocol.h:104
DBUS_ERROR_UNKNOWN_OBJECT
#define DBUS_ERROR_UNKNOWN_OBJECT
Object you invoked a method on isn't known.
Definition dbus-protocol.h:405
DBUS_TYPE_INVALID
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition dbus-protocol.h:62
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition dbus-protocol.h:361
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition dbus-protocol.h:363
DBUS_ERROR_DISCONNECTED
#define DBUS_ERROR_DISCONNECTED
The connection is disconnected and you're trying to use it.
Definition dbus-protocol.h:395
_dbus_counter_new
DBusCounter * _dbus_counter_new(void)
Creates a new DBusCounter.
Definition dbus-resources.c:91
_dbus_counter_get_unix_fd_value
long _dbus_counter_get_unix_fd_value(DBusCounter *counter)
Gets the current value of the unix fd counter.
Definition dbus-resources.c:292
_dbus_counter_unref
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
Definition dbus-resources.c:138
_dbus_counter_get_size_value
long _dbus_counter_get_size_value(DBusCounter *counter)
Gets the current value of the size counter.
Definition dbus-resources.c:276
_dbus_counter_ref
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
Definition dbus-resources.c:118
DBusHandlerResult
DBusHandlerResult
Results that a message handler can return.
Definition dbus-shared.h:69
DBUS_PATH_LOCAL
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition dbus-shared.h:84
DBUS_INTERFACE_LOCAL
#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:107
DBUS_INTERFACE_PEER
#define DBUS_INTERFACE_PEER
The interface supported by most dbus peers.
Definition dbus-shared.h:101
DBUS_HANDLER_RESULT_NEED_MEMORY
@ 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:72
DBUS_HANDLER_RESULT_HANDLED
@ DBUS_HANDLER_RESULT_HANDLED
Message has had its effect - no need to run more handlers.
Definition dbus-shared.h:70
DBUS_HANDLER_RESULT_NOT_YET_HANDLED
@ DBUS_HANDLER_RESULT_NOT_YET_HANDLED
Message has not had any effect - see if other handlers want it.
Definition dbus-shared.h:71
dbus_type_is_valid
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
Definition dbus-signature.c:389
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition dbus-string.c:182
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
Definition dbus-string.c:278
_dbus_string_append_printf
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:1147
_dbus_get_monotonic_time
void _dbus_get_monotonic_time(dbus_int64_t *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
Definition dbus-sysdeps-unix.c:3381
_dbus_exit
void _dbus_exit(int code)
Exit the process, returning the given value.
Definition dbus-sysdeps-unix.c:3641
_dbus_atomic_set_nonzero
void _dbus_atomic_set_nonzero(DBusAtomic *atomic)
Atomically set the value of an integer to something nonzero.
Definition dbus-sysdeps-unix.c:3279
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition dbus-sysdeps-unix.c:3205
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition dbus-sysdeps-unix.c:3233
_dbus_disable_sigpipe
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
Definition dbus-sysdeps-unix.c:3670
_dbus_sleep_milliseconds
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
Definition dbus-sysdeps-unix.c:3542
_dbus_atomic_set_zero
void _dbus_atomic_set_zero(DBusAtomic *atomic)
Atomically set the value of an integer to 0.
Definition dbus-sysdeps-unix.c:3258
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition dbus-sysdeps-unix.c:3178
_dbus_rmutex_new_at_location
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:56
_dbus_cmutex_free_at_location
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex; does nothing if passed a NULL pointer.
Definition dbus-threads.c:110
_dbus_condvar_free_at_location
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a condition variable; does nothing if passed a NULL pointer.
Definition dbus-threads.c:227
_dbus_rmutex_unlock
DBUS_PRIVATE_EXPORT void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition dbus-threads.c:153
_dbus_condvar_wait
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:243
_dbus_condvar_new_at_location
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition dbus-threads.c:202
_dbus_cmutex_new_at_location
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:80
_dbus_condvar_wake_one
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition dbus-threads.c:281
_dbus_condvar_wait_timeout
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:264
_dbus_cmutex_lock
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition dbus-threads.c:139
_dbus_cmutex_unlock
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition dbus-threads.c:167
_dbus_rmutex_free_at_location
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex; does nothing if passed a NULL pointer.
Definition dbus-threads.c:97
DBusMutex
struct DBusMutex DBusMutex
An opaque mutex type provided by the DBusThreadFunctions implementation installed by dbus_threads_ini...
Definition dbus-threads.h:43
_dbus_timeout_list_add_timeout
dbus_bool_t _dbus_timeout_list_add_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Adds a new timeout to the timeout list, invoking the application DBusAddTimeoutFunction if appropriat...
Definition dbus-timeout.c:314
_dbus_timeout_list_free
void _dbus_timeout_list_free(DBusTimeoutList *timeout_list)
Frees a DBusTimeoutList.
Definition dbus-timeout.c:217
_dbus_timeout_list_toggle_timeout
void _dbus_timeout_list_toggle_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout, dbus_bool_t enabled)
Sets a timeout to the given enabled state, invoking the application's DBusTimeoutToggledFunction if a...
Definition dbus-timeout.c:366
_dbus_timeout_list_new
DBusTimeoutList * _dbus_timeout_list_new(void)
Creates a new timeout list.
Definition dbus-timeout.c:200
_dbus_timeout_list_set_functions
dbus_bool_t _dbus_timeout_list_set_functions(DBusTimeoutList *timeout_list, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the timeout functions.
Definition dbus-timeout.c:243
_dbus_timeout_list_remove_timeout
void _dbus_timeout_list_remove_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Removes a timeout from the timeout list, invoking the application's DBusRemoveTimeoutFunction if appr...
Definition dbus-timeout.c:344
dbus_timeout_get_interval
DBUS_EXPORT int dbus_timeout_get_interval(DBusTimeout *timeout)
Gets the timeout interval.
Definition dbus-timeout.c:444
_dbus_transport_set_max_message_size
void _dbus_transport_set_max_message_size(DBusTransport *transport, long size)
See dbus_connection_set_max_message_size().
Definition dbus-transport.c:1225
_dbus_transport_set_max_received_size
void _dbus_transport_set_max_received_size(DBusTransport *transport, long size)
See dbus_connection_set_max_received_size().
Definition dbus-transport.c:1275
_dbus_transport_get_dispatch_status
DBusDispatchStatus _dbus_transport_get_dispatch_status(DBusTransport *transport)
Reports our current dispatch status (whether there's buffered data to be queued as messages,...
Definition dbus-transport.c:1127
_dbus_transport_get_pending_fds_count
int _dbus_transport_get_pending_fds_count(DBusTransport *transport)
Return how many file descriptors are pending in the loader.
Definition dbus-transport.c:1590
_dbus_transport_get_adt_audit_session_data
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().
Definition dbus-transport.c:1403
_dbus_transport_get_windows_user
dbus_bool_t _dbus_transport_get_windows_user(DBusTransport *transport, char **windows_sid_p)
See dbus_connection_get_windows_user().
Definition dbus-transport.c:1505
_dbus_transport_queue_messages
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...
Definition dbus-transport.c:1166
_dbus_transport_get_socket_fd
dbus_bool_t _dbus_transport_get_socket_fd(DBusTransport *transport, DBusSocket *fd_p)
Get the socket file descriptor, if any.
Definition dbus-transport.c:969
_dbus_transport_get_address
const char * _dbus_transport_get_address(DBusTransport *transport)
Gets the address of a transport.
Definition dbus-transport.c:874
_dbus_transport_handle_watch
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...
Definition dbus-transport.c:907
_dbus_transport_ref
DBusTransport * _dbus_transport_ref(DBusTransport *transport)
Increments the reference count for the transport.
Definition dbus-transport.c:469
_dbus_transport_peek_is_authenticated
dbus_bool_t _dbus_transport_peek_is_authenticated(DBusTransport *transport)
Returns TRUE if we have been authenticated.
Definition dbus-transport.c:710
_dbus_transport_set_allow_anonymous
void _dbus_transport_set_allow_anonymous(DBusTransport *transport, dbus_bool_t value)
See dbus_connection_set_allow_anonymous().
Definition dbus-transport.c:1578
_dbus_transport_disconnect
void _dbus_transport_disconnect(DBusTransport *transport)
Closes our end of the connection to a remote application.
Definition dbus-transport.c:511
_dbus_transport_get_max_received_size
long _dbus_transport_get_max_received_size(DBusTransport *transport)
See dbus_connection_get_max_received_size().
Definition dbus-transport.c:1311
_dbus_transport_get_credentials
DBusCredentials * _dbus_transport_get_credentials(DBusTransport *transport)
If the transport has already been authenticated, return its credentials.
Definition dbus-transport.c:1489
_dbus_transport_set_connection
dbus_bool_t _dbus_transport_set_connection(DBusTransport *transport, DBusConnection *connection)
Sets the connection using this transport.
Definition dbus-transport.c:945
_dbus_transport_set_unix_user_function
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().
Definition dbus-transport.c:1439
_dbus_transport_get_max_message_unix_fds
long _dbus_transport_get_max_message_unix_fds(DBusTransport *transport)
See dbus_connection_get_max_message_unix_fds().
Definition dbus-transport.c:1263
_dbus_transport_set_max_received_unix_fds
void _dbus_transport_set_max_received_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_received_unix_fds().
Definition dbus-transport.c:1293
_dbus_transport_unref
void _dbus_transport_unref(DBusTransport *transport)
Decrements the reference count for the transport.
Definition dbus-transport.c:486
_dbus_transport_can_pass_unix_fd
dbus_bool_t _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
Returns TRUE if the transport supports sending unix fds.
Definition dbus-transport.c:861
_dbus_transport_try_to_authenticate
dbus_bool_t _dbus_transport_try_to_authenticate(DBusTransport *transport)
Returns TRUE if we have been authenticated.
Definition dbus-transport.c:733
_dbus_transport_do_iteration
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...
Definition dbus-transport.c:1002
_dbus_transport_get_max_received_unix_fds
long _dbus_transport_get_max_received_unix_fds(DBusTransport *transport)
See dbus_connection_set_max_received_unix_fds().
Definition dbus-transport.c:1323
_dbus_transport_get_is_connected
dbus_bool_t _dbus_transport_get_is_connected(DBusTransport *transport)
Returns TRUE if the transport has not been disconnected.
Definition dbus-transport.c:536
_dbus_transport_set_max_message_unix_fds
void _dbus_transport_set_max_message_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_message_unix_fds().
Definition dbus-transport.c:1238
_dbus_transport_set_pending_fds_function
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...
Definition dbus-transport.c:1603
_dbus_transport_set_windows_user_function
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().
Definition dbus-transport.c:1541
_dbus_transport_get_max_message_size
long _dbus_transport_get_max_message_size(DBusTransport *transport)
See dbus_connection_get_max_message_size().
Definition dbus-transport.c:1251
_dbus_transport_get_unix_process_id
dbus_bool_t _dbus_transport_get_unix_process_id(DBusTransport *transport, unsigned long *pid)
See dbus_connection_get_unix_process_id().
Definition dbus-transport.c:1369
_dbus_transport_open
DBusTransport * _dbus_transport_open(DBusAddressEntry *entry, DBusError *error)
Try to open a new transport for the given address entry.
Definition dbus-transport.c:373
_dbus_transport_get_server_id
const char * _dbus_transport_get_server_id(DBusTransport *transport)
Gets the id of the server we are connected to (see dbus_server_get_id()).
Definition dbus-transport.c:887
_dbus_transport_get_is_anonymous
dbus_bool_t _dbus_transport_get_is_anonymous(DBusTransport *transport)
See dbus_connection_get_is_anonymous().
Definition dbus-transport.c:839
_dbus_transport_get_unix_user
dbus_bool_t _dbus_transport_get_unix_user(DBusTransport *transport, unsigned long *uid)
See dbus_connection_get_unix_user().
Definition dbus-transport.c:1336
dbus_int64_t
_DBUS_GNUC_EXTENSION typedef long dbus_int64_t
A 64-bit signed integer.
Definition dbus-arch-deps.h:37
dbus_uint32_t
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
Definition dbus-arch-deps.h:45
dbus_int32_t
int dbus_int32_t
A 32-bit signed integer on all platforms.
Definition dbus-arch-deps.h:44
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:37
DBUS_INT64_MODIFIER
#define DBUS_INT64_MODIFIER
A string literal for a length modifier that is appropriate to print the dbus_int64_t and dbus_uint64_...
Definition dbus-arch-deps.h:39
_dbus_watch_list_add_watch
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:383
_dbus_watch_list_toggle_watch
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:443
_dbus_watch_list_new
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition dbus-watch.c:234
_dbus_watch_list_free
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition dbus-watch.c:251
_dbus_watch_list_set_functions
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:297
_dbus_watch_list_remove_watch
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:416
DBusAddressEntry
Internals of DBusAddressEntry.
Definition dbus-address.c:49
DBusAtomic
An atomic integer safe to increment or decrement from multiple threads.
Definition dbus-sysdeps.h:340
DBusCMutex
Definition dbus-sysdeps-pthread.c:55
DBusCondVar
Definition dbus-sysdeps-pthread.c:59
DBusConnection
Implementation details of DBusConnection.
Definition dbus-connection.c:259
DBusConnection::dispatch_status_data
void * dispatch_status_data
Application data for dispatch_status_function.
Definition dbus-connection.c:301
DBusConnection::n_outgoing
int n_outgoing
Length of outgoing queue.
Definition dbus-connection.c:277
DBusConnection::slot_list
DBusDataSlotList slot_list
Data stored by allocated integer ID.
Definition dbus-connection.c:289
DBusConnection::dispatch_acquired
dbus_bool_t dispatch_acquired
Someone has dispatch path (can drain incoming queue).
Definition dbus-connection.c:314
DBusConnection::dispatch_cond
DBusCondVar * dispatch_cond
Notify when dispatch_acquired is available.
Definition dbus-connection.c:265
DBusConnection::wakeup_main_function
DBusWakeupMainFunction wakeup_main_function
Function to wake up the mainloop.
Definition dbus-connection.c:296
DBusConnection::exit_on_disconnect
unsigned int exit_on_disconnect
If TRUE, exit after handling disconnect signal.
Definition dbus-connection.c:319
DBusConnection::filter_list
DBusList * filter_list
List of filters.
Definition dbus-connection.c:286
DBusConnection::have_connection_lock
unsigned int have_connection_lock
Used to check locking.
Definition dbus-connection.c:334
DBusConnection::disconnected_message_processed
unsigned int disconnected_message_processed
We did our default handling of the disconnected message, such as closing the connection.
Definition dbus-connection.c:329
DBusConnection::client_serial
dbus_uint32_t client_serial
Client serial.
Definition dbus-connection.c:293
DBusConnection::disconnected_message_arrived
unsigned int disconnected_message_arrived
We popped or are dispatching the disconnected message.
Definition dbus-connection.c:325
DBusConnection::outgoing_counter
DBusCounter * outgoing_counter
Counts size of outgoing messages.
Definition dbus-connection.c:280
DBusConnection::builtin_filters_enabled
unsigned int builtin_filters_enabled
If TRUE, handle org.freedesktop.DBus.Peer messages automatically, whether they have a bus name or not...
Definition dbus-connection.c:321
DBusConnection::io_path_cond
DBusCondVar * io_path_cond
Notify when io_path_acquired is available.
Definition dbus-connection.c:267
DBusConnection::refcount
DBusAtomic refcount
Reference count.
Definition dbus-connection.c:260
DBusConnection::outgoing_messages
DBusList * outgoing_messages
Queue of messages we need to send, send the end of the list first.
Definition dbus-connection.c:269
DBusConnection::free_dispatch_status_data
DBusFreeFunction free_dispatch_status_data
free dispatch_status_data
Definition dbus-connection.c:302
DBusConnection::slot_mutex
DBusRMutex * slot_mutex
Lock on slot_list so overall connection lock need not be taken.
Definition dbus-connection.c:288
DBusConnection::free_wakeup_main_data
DBusFreeFunction free_wakeup_main_data
free wakeup_main_data
Definition dbus-connection.c:298
DBusConnection::transport
DBusTransport * transport
Object that sends/receives messages over network.
Definition dbus-connection.c:282
DBusConnection::mutex
DBusRMutex * mutex
Lock on the entire DBusConnection.
Definition dbus-connection.c:262
DBusConnection::n_incoming
int n_incoming
Length of incoming queue.
Definition dbus-connection.c:278
DBusConnection::io_path_acquired
dbus_bool_t io_path_acquired
Someone has transport io path (can use the transport to read/write messages).
Definition dbus-connection.c:315
DBusConnection::disconnect_message_link
DBusList * disconnect_message_link
Preallocated list node for queueing the disconnection message.
Definition dbus-connection.c:294
DBusConnection::io_path_mutex
DBusCMutex * io_path_mutex
Protects io_path_acquired.
Definition dbus-connection.c:266
DBusConnection::incoming_messages
DBusList * incoming_messages
Queue of messages we have received, end of the list received most recently.
Definition dbus-connection.c:270
DBusConnection::shareable
unsigned int shareable
TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more...
Definition dbus-connection.c:317
DBusConnection::route_peer_messages
unsigned int route_peer_messages
If TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don't handle them automatically.
Definition dbus-connection.c:323
DBusConnection::watches
DBusWatchList * watches
Stores active watches.
Definition dbus-connection.c:283
DBusConnection::wakeup_main_data
void * wakeup_main_data
Application data for wakeup_main_function.
Definition dbus-connection.c:297
DBusConnection::objects
DBusObjectTree * objects
Object path handlers registered with this connection.
Definition dbus-connection.c:306
DBusConnection::server_guid
char * server_guid
GUID of server if we are in shared_connections, NULL if server GUID is unknown or connection is priva...
Definition dbus-connection.c:308
DBusConnection::pending_replies
DBusHashTable * pending_replies
Hash of message serials to DBusPendingCall.
Definition dbus-connection.c:291
DBusConnection::dispatch_mutex
DBusCMutex * dispatch_mutex
Protects dispatch_acquired.
Definition dbus-connection.c:264
DBusConnection::message_borrowed
DBusMessage * message_borrowed
Filled in if the first incoming message has been borrowed; dispatch_acquired will be set by the borro...
Definition dbus-connection.c:273
DBusConnection::timeouts
DBusTimeoutList * timeouts
Stores active timeouts.
Definition dbus-connection.c:284
DBusConnection::last_dispatch_status
DBusDispatchStatus last_dispatch_status
The last dispatch status we reported to the application.
Definition dbus-connection.c:304
DBusConnection::dispatch_status_function
DBusDispatchStatusFunction dispatch_status_function
Function on dispatch status changes.
Definition dbus-connection.c:300
DBusConnection::expired_messages
DBusList * expired_messages
Messages that will be released when we next unlock.
Definition dbus-connection.c:271
DBusCounter
Internals of DBusCounter.
Definition dbus-resources.c:57
DBusCredentials
Definition dbus-credentials.c:60
DBusDataSlotAllocator
An allocator that tracks a set of slot IDs.
Definition dbus-dataslot.h:58
DBusDataSlotList
Data structure that stores the actual user data set at a given slot.
Definition dbus-dataslot.h:72
DBusError
Object representing an exception.
Definition dbus-errors.h:51
DBusError::name
const char * name
public error name field
Definition dbus-errors.h:52
DBusError::message
const char * message
public error message field
Definition dbus-errors.h:53
DBusHashIter
Hash iterator object.
Definition dbus-hash.h:50
DBusHashTable
Internals of DBusHashTable.
Definition dbus-hash.c:175
DBusList
A node in a linked list.
Definition dbus-list.h:37
DBusList::data
void * data
Data stored at this element.
Definition dbus-list.h:40
DBusMessageFilter
Internal struct representing a message filter function.
Definition dbus-connection.c:231
DBusMessageFilter::refcount
DBusAtomic refcount
Reference count.
Definition dbus-connection.c:232
DBusMessageFilter::function
DBusHandleMessageFunction function
Function to call to filter.
Definition dbus-connection.c:233
DBusMessageFilter::user_data
void * user_data
User data for the function.
Definition dbus-connection.c:234
DBusMessageFilter::free_user_data_function
DBusFreeFunction free_user_data_function
Function to free the user data.
Definition dbus-connection.c:235
DBusMessageIter
DBusMessageIter struct; contains no public fields.
Definition dbus-message.h:64
DBusMessage
Internals of DBusMessage.
Definition dbus-message-private.h:102
DBusObjectPathVTable
Virtual table that must be implemented to handle a portion of the object path hierarchy.
Definition dbus-connection.h:391
DBusObjectTree
Internals of DBusObjectTree.
Definition dbus-object-tree.c:61
DBusPendingCall
Implementation details of DBusPendingCall - all fields are private.
Definition dbus-pending-call.c:65
DBusPreallocatedSend
Internals of DBusPreallocatedSend.
Definition dbus-connection.c:243
DBusPreallocatedSend::connection
DBusConnection * connection
Connection we'd send the message to.
Definition dbus-connection.c:244
DBusPreallocatedSend::counter_link
DBusList * counter_link
Preallocated link in the resource counter.
Definition dbus-connection.c:246
DBusPreallocatedSend::queue_link
DBusList * queue_link
Preallocated link in the queue.
Definition dbus-connection.c:245
DBusRMutex
Definition dbus-sysdeps-pthread.c:51
DBusSocket
Socket interface.
Definition dbus-sysdeps.h:185
DBusString
Definition dbus-string.h:47
DBusTimeoutList
DBusTimeoutList implementation details.
Definition dbus-timeout.c:183
DBusTimeout
Internals of DBusTimeout.
Definition dbus-timeout.c:43
DBusTransport
Object representing a transport such as a socket.
Definition dbus-transport-protected.h:83
DBusWatchList
DBusWatchList implementation details.
Definition dbus-watch.c:217
DBusWatch
Implementation of DBusWatch.
Definition dbus-watch.c:43