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...)