13 #include <dbus/dbus.h>
21 static GList *conn_dispatches = NULL;
38 update_dispatch_status(DBusConnection *connection,
39 DBusDispatchStatus new_status,
void *
data)
41 if (new_status == DBUS_DISPATCH_DATA_REMAINS) {
42 crm_trace(
"DBus connection has messages available for dispatch");
43 conn_dispatches = g_list_prepend(conn_dispatches, connection);
45 crm_trace(
"DBus connection has no messages available for dispatch "
46 "(status %d)", new_status);
55 dispatch_messages(
void)
57 for (GList *gIter = conn_dispatches; gIter != NULL; gIter = gIter->next) {
58 DBusConnection *connection = gIter->data;
60 while (dbus_connection_get_dispatch_status(connection)
61 == DBUS_DISPATCH_DATA_REMAINS) {
62 crm_trace(
"Dispatching available messages on DBus connection");
63 dbus_connection_dispatch(connection);
66 g_list_free(conn_dispatches);
67 conn_dispatches = NULL;
80 dbus_watch_flags_to_string(
int flags)
82 const char *watch_type;
84 if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE)) {
85 watch_type =
"read/write";
86 }
else if (flags & DBUS_WATCH_READABLE) {
88 }
else if (flags & DBUS_WATCH_WRITABLE) {
91 watch_type =
"neither read nor write";
108 dispatch_fd_data(gpointer userdata)
111 DBusWatch *watch = userdata;
112 int flags = dbus_watch_get_flags(watch);
113 bool enabled = dbus_watch_get_enabled (watch);
115 crm_trace(
"Dispatching DBus watch for file descriptor %d "
116 "with flags 0x%x (%s)",
117 dbus_watch_get_unix_fd(watch), flags,
118 dbus_watch_flags_to_string(flags));
120 if (enabled && (flags & (DBUS_WATCH_READABLE|DBUS_WATCH_WRITABLE))) {
121 oom = !dbus_watch_handle(watch, flags);
123 }
else if (enabled) {
124 oom = !dbus_watch_handle(watch, DBUS_WATCH_ERROR);
127 if (flags != dbus_watch_get_flags(watch)) {
128 flags = dbus_watch_get_flags(watch);
129 crm_trace(
"Dispatched DBus file descriptor watch: now 0x%x (%s)",
130 flags, dbus_watch_flags_to_string(flags));
134 crm_crit(
"Could not dispatch DBus file descriptor data: Out of memory");
142 watch_fd_closed(gpointer userdata)
144 crm_trace(
"DBus watch for file descriptor %d is now closed",
145 dbus_watch_get_unix_fd((DBusWatch *) userdata));
150 .destroy = watch_fd_closed,
154 add_dbus_watch(DBusWatch *watch,
void *data)
156 int fd = dbus_watch_get_unix_fd(watch);
159 watch, &pcmk_dbus_cb);
161 crm_trace(
"Added DBus watch for file descriptor %d", fd);
162 dbus_watch_set_data(watch, client, NULL);
167 toggle_dbus_watch(DBusWatch *watch,
void *data)
170 crm_debug(
"DBus watch for file descriptor %d is now %s",
171 dbus_watch_get_unix_fd(watch),
172 (dbus_watch_get_enabled(watch)?
"enabled" :
"disabled"));
176 remove_dbus_watch(DBusWatch *watch,
void *data)
178 crm_trace(
"Removed DBus watch for file descriptor %d",
179 dbus_watch_get_unix_fd(watch));
184 register_watch_functions(DBusConnection *connection)
186 dbus_connection_set_watch_functions(connection, add_dbus_watch,
188 toggle_dbus_watch, NULL, NULL);
199 timer_popped(gpointer data)
202 dbus_timeout_get_interval((DBusTimeout *) data));
203 dbus_timeout_handle(data);
208 add_dbus_timer(DBusTimeout *
timeout,
void *data)
210 int interval_ms = dbus_timeout_get_interval(timeout);
211 guint
id = g_timeout_add(interval_ms, timer_popped, timeout);
214 dbus_timeout_set_data(timeout, GUINT_TO_POINTER(
id), NULL);
216 crm_trace(
"Added %dms DBus timer", interval_ms);
221 remove_dbus_timer(DBusTimeout *timeout,
void *data)
223 void *vid = dbus_timeout_get_data(timeout);
224 guint
id = GPOINTER_TO_UINT(vid);
226 crm_trace(
"Removing %dms DBus timer", dbus_timeout_get_interval(timeout));
229 dbus_timeout_set_data(timeout, 0, NULL);
234 toggle_dbus_timer(DBusTimeout *timeout,
void *data)
236 bool enabled = dbus_timeout_get_enabled(timeout);
239 dbus_timeout_get_interval(timeout), (enabled?
"off":
"on"));
241 add_dbus_timer(timeout, data);
243 remove_dbus_timer(timeout, data);
248 register_timer_functions(DBusConnection *connection)
250 dbus_connection_set_timeout_functions(connection, add_dbus_timer,
252 toggle_dbus_timer, NULL, NULL);
263 DBusConnection *connection;
265 dbus_error_init(&err);
266 connection = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
267 if (dbus_error_is_set(&err)) {
268 crm_err(
"Could not connect to DBus: %s", err.message);
269 dbus_error_free(&err);
272 if (connection == NULL) {
279 dbus_connection_set_exit_on_disconnect(connection, FALSE);
282 register_timer_functions(connection);
283 register_watch_functions(connection);
284 dbus_connection_set_dispatch_status_function(connection,
285 update_dispatch_status,
289 update_dispatch_status(connection,
290 dbus_connection_get_dispatch_status(connection),
307 #define ERR_NO_REQUEST "org.clusterlabs.pacemaker.NoRequest"
308 #define ERR_NO_REPLY "org.clusterlabs.pacemaker.NoReply"
309 #define ERR_INVALID_REPLY "org.clusterlabs.pacemaker.InvalidReply"
310 #define ERR_INVALID_REPLY_METHOD "org.clusterlabs.pacemaker.InvalidReply.Method"
311 #define ERR_INVALID_REPLY_SIGNAL "org.clusterlabs.pacemaker.InvalidReply.Signal"
312 #define ERR_INVALID_REPLY_TYPE "org.clusterlabs.pacemaker.InvalidReply.Type"
313 #define ERR_SEND_FAILED "org.clusterlabs.pacemaker.SendFailed"
336 dbus_error_init(&error);
338 if (pending == NULL) {
341 }
else if (reply == NULL) {
345 DBusMessageIter args;
346 int dtype = dbus_message_get_type(reply);
349 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
353 dbus_message_iter_init(reply, &args);
354 crm_trace(
"Received DBus reply with argument type '%s'",
355 (sig = dbus_message_iter_get_signature(&args)));
361 case DBUS_MESSAGE_TYPE_INVALID:
365 case DBUS_MESSAGE_TYPE_METHOD_CALL:
367 "Invalid reply (method call)");
369 case DBUS_MESSAGE_TYPE_SIGNAL:
371 "Invalid reply (signal)");
373 case DBUS_MESSAGE_TYPE_ERROR:
374 dbus_set_error_from_message(&error, reply);
378 "Unknown reply type %d", dtype);
382 if (dbus_error_is_set(&error)) {
383 crm_trace(
"DBus reply indicated error '%s' (%s)",
384 error.name, error.message);
386 dbus_error_init(ret);
387 dbus_move_error(&error, ret);
389 dbus_error_free(&error);
414 DBusError *error,
int timeout)
416 const char *method = NULL;
417 DBusMessage *reply = NULL;
418 DBusPendingCall* pending = NULL;
420 CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL);
421 method = dbus_message_get_member (msg);
425 dbus_error_init(error);
434 if (!dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
437 "Could not queue DBus '%s' request", method);
442 dbus_connection_flush(connection);
446 dbus_pending_call_block(pending);
449 reply = dbus_pending_call_steal_reply(pending);
456 dbus_pending_call_unref(pending);
478 void (*done)(DBusPendingCall *pending,
void *user_data),
479 void *user_data,
int timeout)
481 const char *method = NULL;
482 DBusPendingCall* pending = NULL;
485 CRM_ASSERT(dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL);
486 method = dbus_message_get_member(msg);
494 if (!dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
495 crm_err(
"Could not send DBus %s message: failed", method);
498 }
else if (pending == NULL) {
499 crm_err(
"Could not send DBus %s message: connection may be closed",
504 if (dbus_pending_call_get_completed(pending)) {
505 crm_info(
"DBus %s message completed too soon", method);
510 if (!dbus_pending_call_set_notify(pending, done, user_data, NULL)) {
518 const char *
function,
int line)
521 DBusMessageIter lfield;
524 if (dbus_message_iter_init(msg, &lfield)) {
531 "DBus reply has empty parameter list (expected '%c')",
536 dtype = dbus_message_iter_get_arg_type(field);
538 if (dtype != expected) {
539 DBusMessageIter args;
542 dbus_message_iter_init(msg, &args);
543 sig = dbus_message_iter_get_signature(&args);
545 "DBus reply has unexpected type "
546 "(expected '%c' not '%c' in '%s')",
547 expected, dtype, sig);
564 #define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties"
572 struct property_query {
581 free_property_query(
struct property_query *data)
590 handle_query_result(DBusMessage *reply,
struct property_query *data)
594 DBusMessageIter args;
595 DBusMessageIter variant_iter;
596 DBusBasicValue value;
600 crm_err(
"DBus query for %s property '%s' failed: %s",
601 data->object, data->name, error.message);
602 dbus_error_free(&error);
607 dbus_message_iter_init(reply, &args);
609 __func__, __LINE__)) {
610 crm_err(
"DBus query for %s property '%s' failed: Unexpected reply type",
611 data->object, data->name);
616 dbus_message_iter_recurse(&args, &variant_iter);
618 __func__, __LINE__)) {
619 crm_err(
"DBus query for %s property '%s' failed: "
620 "Unexpected variant type", data->object, data->name);
623 dbus_message_iter_get_basic(&variant_iter, &value);
626 dbus_message_iter_next(&variant_iter);
627 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_INVALID) {
628 crm_err(
"DBus query for %s property '%s' failed: "
629 "Too many arguments in reply",
630 data->object, data->name);
633 dbus_message_iter_next(&args);
634 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INVALID) {
635 crm_err(
"DBus query for %s property '%s' failed: "
636 "Too many arguments in reply", data->object, data->name);
640 crm_trace(
"DBus query result for %s: %s='%s'",
641 data->object, data->name, (value.str? value.str :
""));
643 if (data->callback) {
644 data->callback(data->name, (value.str? value.str :
""), data->userdata);
647 output = strdup(value.str? value.str :
"");
651 free_property_query(data);
656 async_query_result_cb(DBusPendingCall *pending,
void *user_data)
658 DBusMessage *reply = NULL;
662 reply = dbus_pending_call_steal_reply(pending);
665 value = handle_query_result(reply, user_data);
669 dbus_message_unref(reply);
695 const char *obj,
const gchar * iface,
const char *name,
697 DBusPendingCall **pending,
int timeout)
701 struct property_query *query_data = NULL;
703 CRM_CHECK((connection != NULL) && (target != NULL) && (obj != NULL)
704 && (iface != NULL) && (name != NULL),
return NULL);
706 crm_trace(
"Querying DBus %s for %s property '%s'",
712 crm_err(
"DBus query for %s property '%s' failed: "
713 "Unable to create message", obj, name);
718 if (!dbus_message_append_args(msg,
719 DBUS_TYPE_STRING, &iface,
720 DBUS_TYPE_STRING, &name,
721 DBUS_TYPE_INVALID)) {
722 crm_err(
"DBus query for %s property '%s' failed: "
723 "Could not append arguments", obj, name);
724 dbus_message_unref(msg);
728 query_data = malloc(
sizeof(
struct property_query));
729 if (query_data == NULL) {
730 crm_crit(
"DBus query for %s property '%s' failed: Out of memory",
732 dbus_message_unref(msg);
736 query_data->target = strdup(target);
737 query_data->object = strdup(obj);
738 query_data->callback = callback;
739 query_data->userdata = userdata;
740 query_data->name = strdup(name);
742 && (query_data->object != NULL)
743 && (query_data->name != NULL),
744 free_property_query(query_data);
745 dbus_message_unref(msg);
748 if (query_data->callback) {
749 DBusPendingCall *local_pending;
751 local_pending =
pcmk_dbus_send(msg, connection, async_query_result_cb,
752 query_data, timeout);
753 if (local_pending == NULL) {
755 free_property_query(query_data);
760 *pending = local_pending;
767 output = handle_query_result(reply, query_data);
770 dbus_message_unref(reply);
774 dbus_message_unref(msg);
#define CRM_CHECK(expr, failure_action)
#define ERR_INVALID_REPLY_SIGNAL
#define crm_crit(fmt, args...)
mainloop_io_t * mainloop_add_fd(const char *name, int priority, int fd, void *userdata, struct mainloop_fd_callbacks *callbacks)
#define BUS_PROPERTY_IFACE
#define ERR_INVALID_REPLY_TYPE
void pcmk_dbus_disconnect(DBusConnection *connection)
#define DBUS_TIMEOUT_USE_DEFAULT
struct mainloop_io_s mainloop_io_t
void(* property_callback_func)(const char *name, const char *value, void *userdata)
int(* dispatch)(gpointer userdata)
Dispatch function for mainloop file descriptor with data ready.
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
bool pcmk_dbus_find_error(DBusPendingCall *pending, DBusMessage *reply, DBusError *ret)
#define crm_debug(fmt, args...)
#define crm_trace(fmt, args...)
DBusPendingCall * pcmk_dbus_send(DBusMessage *msg, DBusConnection *connection, void(*done)(DBusPendingCall *pending, void *user_data), void *user_data, int timeout)
DBusConnection * pcmk_dbus_connect(void)
#define ERR_INVALID_REPLY_METHOD
#define crm_err(fmt, args...)
bool pcmk_dbus_type_check(DBusMessage *msg, DBusMessageIter *field, int expected, const char *function, int line)
void mainloop_del_fd(mainloop_io_t *client)
#define ERR_INVALID_REPLY
char * pcmk_dbus_get_property(DBusConnection *connection, const char *target, const char *obj, const gchar *iface, const char *name, property_callback_func callback, void *userdata, DBusPendingCall **pending, int timeout)
DBusMessage * pcmk_dbus_send_recv(DBusMessage *msg, DBusConnection *connection, DBusError *error, int timeout)
#define crm_info(fmt, args...)