12 #include <dbus/dbus.h>    20 static GList *conn_dispatches = NULL;
    37 update_dispatch_status(DBusConnection *connection,
    38                        DBusDispatchStatus new_status, 
void *
data)
    40     if (new_status == DBUS_DISPATCH_DATA_REMAINS) {
    41         crm_trace(
"DBus connection has messages available for dispatch");
    42         conn_dispatches = g_list_prepend(conn_dispatches, connection);
    44         crm_trace(
"DBus connection has no messages available for dispatch "    45                   "(status %d)", new_status);
    54 dispatch_messages(
void)
    56     for (GList *gIter = conn_dispatches; gIter != NULL; gIter = gIter->next) {
    57         DBusConnection *connection = gIter->data;
    59         while (dbus_connection_get_dispatch_status(connection)
    60                == DBUS_DISPATCH_DATA_REMAINS) {
    61             crm_trace(
"Dispatching available messages on DBus connection");
    62             dbus_connection_dispatch(connection);
    65     g_list_free(conn_dispatches);
    66     conn_dispatches = NULL;
    79 dbus_watch_flags_to_string(
int flags)
    81     const char *watch_type;
    83     if ((
flags & DBUS_WATCH_READABLE) && (
flags & DBUS_WATCH_WRITABLE)) {
    84         watch_type = 
"read/write";
    85     } 
else if (
flags & DBUS_WATCH_READABLE) {
    87     } 
else if (
flags & DBUS_WATCH_WRITABLE) {
    90         watch_type = 
"neither read nor write";
   107 dispatch_fd_data(gpointer userdata)
   110     DBusWatch *watch = userdata;
   111     int flags = dbus_watch_get_flags(watch);
   112     bool enabled = dbus_watch_get_enabled (watch);
   114     crm_trace(
"Dispatching DBus watch for file descriptor %d "   115               "with flags 0x%x (%s)",
   116               dbus_watch_get_unix_fd(watch), 
flags,
   117               dbus_watch_flags_to_string(
flags));
   119     if (enabled && (
flags & (DBUS_WATCH_READABLE|DBUS_WATCH_WRITABLE))) {
   120         oom = !dbus_watch_handle(watch, 
flags);
   122     } 
else if (enabled) {
   123         oom = !dbus_watch_handle(watch, DBUS_WATCH_ERROR);
   126     if (
flags != dbus_watch_get_flags(watch)) {
   127         flags = dbus_watch_get_flags(watch);
   128         crm_trace(
"Dispatched DBus file descriptor watch: now 0x%x (%s)",
   133         crm_crit(
"Could not dispatch DBus file descriptor data: Out of memory");
   141 watch_fd_closed(gpointer userdata)
   143     crm_trace(
"DBus watch for file descriptor %d is now closed",
   144               dbus_watch_get_unix_fd((DBusWatch *) userdata));
   149     .destroy = watch_fd_closed,
   153 add_dbus_watch(DBusWatch *watch, 
void *
data)
   155     int fd = dbus_watch_get_unix_fd(watch);
   158                                             watch, &pcmk_dbus_cb);
   160     crm_trace(
"Added DBus watch for file descriptor %d", fd);
   161     dbus_watch_set_data(watch, client, NULL);
   166 toggle_dbus_watch(DBusWatch *watch, 
void *
data)
   169     crm_debug(
"DBus watch for file descriptor %d is now %s",
   170               dbus_watch_get_unix_fd(watch),
   171               (dbus_watch_get_enabled(watch)? 
"enabled" : 
"disabled"));
   175 remove_dbus_watch(DBusWatch *watch, 
void *
data)
   177     crm_trace(
"Removed DBus watch for file descriptor %d",
   178               dbus_watch_get_unix_fd(watch));
   183 register_watch_functions(DBusConnection *connection)
   185     dbus_connection_set_watch_functions(connection, add_dbus_watch,
   187                                         toggle_dbus_watch, NULL, NULL);
   198 timer_popped(gpointer 
data)
   201               dbus_timeout_get_interval((DBusTimeout *) 
data));
   202     dbus_timeout_handle(
data);
   209     int interval_ms = dbus_timeout_get_interval(
timeout);
   210     guint 
id = g_timeout_add(interval_ms, timer_popped, 
timeout);
   213         dbus_timeout_set_data(
timeout, GUINT_TO_POINTER(
id), NULL);
   215     crm_trace(
"Added %dms DBus timer", interval_ms);
   220 remove_dbus_timer(DBusTimeout *
timeout, 
void *
data)
   222     void *vid = dbus_timeout_get_data(
timeout);
   223     guint 
id = GPOINTER_TO_UINT(vid);
   228         dbus_timeout_set_data(
timeout, 0, NULL);
   233 toggle_dbus_timer(DBusTimeout *
timeout, 
void *
data)
   235     bool enabled = dbus_timeout_get_enabled(
timeout);
   238               dbus_timeout_get_interval(
timeout), (enabled? 
"off": 
"on"));
   247 register_timer_functions(DBusConnection *connection)
   249     dbus_connection_set_timeout_functions(connection, add_dbus_timer,
   251                                           toggle_dbus_timer, NULL, NULL);
   262     DBusConnection *connection;
   264     dbus_error_init(&err);
   265     connection = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
   266     if (dbus_error_is_set(&err)) {
   267         crm_err(
"Could not connect to DBus: %s", err.message);
   268         dbus_error_free(&err);
   271     if (connection == NULL) {
   278     dbus_connection_set_exit_on_disconnect(connection, FALSE);
   281     register_timer_functions(connection);
   282     register_watch_functions(connection);
   283     dbus_connection_set_dispatch_status_function(connection,
   284                                                  update_dispatch_status,
   288     update_dispatch_status(connection,
   289                            dbus_connection_get_dispatch_status(connection),
   306 #define ERR_NO_REQUEST           "org.clusterlabs.pacemaker.NoRequest"   307 #define ERR_NO_REPLY             "org.clusterlabs.pacemaker.NoReply"   308 #define ERR_INVALID_REPLY        "org.clusterlabs.pacemaker.InvalidReply"   309 #define ERR_INVALID_REPLY_METHOD "org.clusterlabs.pacemaker.InvalidReply.Method"   310 #define ERR_INVALID_REPLY_SIGNAL "org.clusterlabs.pacemaker.InvalidReply.Signal"   311 #define ERR_INVALID_REPLY_TYPE   "org.clusterlabs.pacemaker.InvalidReply.Type"   312 #define ERR_SEND_FAILED          "org.clusterlabs.pacemaker.SendFailed"   335     dbus_error_init(&error);
   337     if (pending == NULL) {
   340     } 
else if (reply == NULL) {
   344         DBusMessageIter args;
   345         int dtype = dbus_message_get_type(reply);
   348             case DBUS_MESSAGE_TYPE_METHOD_RETURN:
   352                     dbus_message_iter_init(reply, &args);
   353                     crm_trace(
"Received DBus reply with argument type '%s'",
   354                               (sig = dbus_message_iter_get_signature(&args)));
   360             case DBUS_MESSAGE_TYPE_INVALID:
   364             case DBUS_MESSAGE_TYPE_METHOD_CALL:
   366                                      "Invalid reply (method call)");
   368             case DBUS_MESSAGE_TYPE_SIGNAL:
   370                                      "Invalid reply (signal)");
   372             case DBUS_MESSAGE_TYPE_ERROR:
   373                 dbus_set_error_from_message(&error, reply);
   377                                "Unknown reply type %d", dtype);
   381     if (dbus_error_is_set(&error)) {
   382         crm_trace(
"DBus reply indicated error '%s' (%s)",
   383                   error.name, error.message);
   385             dbus_error_init(ret);
   386             dbus_move_error(&error, ret);
   388             dbus_error_free(&error);
   415     const char *method = NULL;
   416     DBusMessage *reply = NULL;
   417     DBusPendingCall* pending = NULL;
   419     CRM_ASSERT(dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL);
   420     method = dbus_message_get_member (msg);
   424         dbus_error_init(error);
   433     if (!dbus_connection_send_with_reply(connection, msg, &pending, 
timeout)) {
   436                            "Could not queue DBus '%s' request", method);
   441     dbus_connection_flush(connection);
   445         dbus_pending_call_block(pending);
   448         reply = dbus_pending_call_steal_reply(pending);
   455         dbus_pending_call_unref(pending);
   477                void (*done)(DBusPendingCall *pending, 
void *user_data),
   480     const char *method = NULL;
   481     DBusPendingCall* pending = NULL;
   484     CRM_ASSERT(dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL);
   485     method = dbus_message_get_member(msg);
   493     if (!dbus_connection_send_with_reply(connection, msg, &pending, 
timeout)) {
   494         crm_err(
"Could not send DBus %s message: failed", method);
   497     } 
else if (pending == NULL) {
   498         crm_err(
"Could not send DBus %s message: connection may be closed",
   503     if (dbus_pending_call_get_completed(pending)) {
   504         crm_info(
"DBus %s message completed too soon", method);
   509     if (!dbus_pending_call_set_notify(pending, done, user_data, NULL)) {
   517                      const char *
function, 
int line)
   520     DBusMessageIter lfield;
   523         if (dbus_message_iter_init(msg, &lfield)) {
   530                          "DBus reply has empty parameter list (expected '%c')",
   535     dtype = dbus_message_iter_get_arg_type(field);
   537     if (dtype != expected) {
   538         DBusMessageIter args;
   541         dbus_message_iter_init(msg, &args);
   542         sig = dbus_message_iter_get_signature(&args);
   544                          "DBus reply has unexpected type "   545                          "(expected '%c' not '%c' in '%s')",
   546                          expected, dtype, sig);
   563 #define BUS_PROPERTY_IFACE "org.freedesktop.DBus.Properties"   571 struct property_query {
   580 free_property_query(
struct property_query *
data)
   589 handle_query_result(DBusMessage *reply, 
struct property_query *
data)
   593     DBusMessageIter args;
   594     DBusMessageIter variant_iter;
   595     DBusBasicValue value;
   599         crm_err(
"DBus query for %s property '%s' failed: %s",
   600                 data->object, 
data->name, error.message);
   601         dbus_error_free(&error);
   606     dbus_message_iter_init(reply, &args);
   608                               __func__, __LINE__)) {
   609         crm_err(
"DBus query for %s property '%s' failed: Unexpected reply type",
   615     dbus_message_iter_recurse(&args, &variant_iter);
   617                               __func__, __LINE__)) {
   618         crm_err(
"DBus query for %s property '%s' failed: "   619                 "Unexpected variant type", 
data->object, 
data->name);
   622     dbus_message_iter_get_basic(&variant_iter, &value);
   625     dbus_message_iter_next(&variant_iter);
   626     if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_INVALID) {
   627         crm_err(
"DBus query for %s property '%s' failed: "   628                 "Too many arguments in reply",
   632     dbus_message_iter_next(&args);
   633     if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INVALID) {
   634         crm_err(
"DBus query for %s property '%s' failed: "   635                 "Too many arguments in reply", 
data->object, 
data->name);
   639     crm_trace(
"DBus query result for %s: %s='%s'",
   640               data->object, 
data->name, (value.str? value.str : 
""));
   642     if (
data->callback) {   
   643         data->callback(
data->name, (value.str? value.str : 
""), 
data->userdata);
   646         output = strdup(value.str? value.str : 
"");
   650     free_property_query(
data);
   655 async_query_result_cb(DBusPendingCall *pending, 
void *user_data)
   657     DBusMessage *reply = NULL;
   661         reply = dbus_pending_call_steal_reply(pending);
   664     value = handle_query_result(reply, user_data);
   668         dbus_message_unref(reply);
   694                        const char *obj, 
const gchar * iface, 
const char *
name,
   696                        DBusPendingCall **pending, 
int timeout)
   700     struct property_query *query_data = NULL;
   703               && (iface != NULL) && (
name != NULL), 
return NULL);
   705     crm_trace(
"Querying DBus %s for %s property '%s'",
   711         crm_err(
"DBus query for %s property '%s' failed: "   712                 "Unable to create message", obj, 
name);
   717     if (!dbus_message_append_args(msg,
   718                                   DBUS_TYPE_STRING, &iface,
   719                                   DBUS_TYPE_STRING, &
name,
   720                                   DBUS_TYPE_INVALID)) {
   721         crm_err(
"DBus query for %s property '%s' failed: "   722                 "Could not append arguments", obj, 
name);
   723         dbus_message_unref(msg);
   727     query_data = malloc(
sizeof(
struct property_query));
   728     if (query_data == NULL) {
   729         crm_crit(
"DBus query for %s property '%s' failed: Out of memory",
   731         dbus_message_unref(msg);
   735     query_data->target = strdup(
target);
   736     query_data->object = strdup(obj);
   737     query_data->callback = callback;
   738     query_data->userdata = userdata;
   739     query_data->name = strdup(
name);
   741                   && (query_data->object != NULL)
   742                   && (query_data->name != NULL),
   743               free_property_query(query_data);
   744               dbus_message_unref(msg);
   747     if (query_data->callback) { 
   748         DBusPendingCall *local_pending;
   750         local_pending = 
pcmk_dbus_send(msg, connection, async_query_result_cb,
   752         if (local_pending == NULL) {
   754             free_property_query(query_data);
   759             *pending = local_pending;
   766         output = handle_query_result(reply, query_data);
   769             dbus_message_unref(reply);
   773     dbus_message_unref(msg);
 #define CRM_CHECK(expr, failure_action)
 
void(* property_callback_func)(const char *name, const char *value, void *userdata)
 
#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
 
#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)
 
int(* dispatch)(gpointer userdata)
Dispatch function for mainloop file descriptor with data ready. 
 
#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...)