/** * Send the current profile id * * @param method_call A DBusMessage to reply to * @return TRUE */ static gboolean send_current_color_profile(DBusMessage *method_call) { DBusMessage *msg = 0; const char *val = color_profile_name ?: COLOR_PROFILE_ID_HARDCODED; if( method_call ) msg = dbus_new_method_reply(method_call); else msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_COLOR_PROFILE_SIG); if( !msg ) goto EXIT; if( !dbus_message_append_args(msg, DBUS_TYPE_STRING, &val, DBUS_TYPE_INVALID) ) goto EXIT; dbus_send_message(msg), msg = 0; EXIT: if( msg ) dbus_message_unref(msg); return TRUE; }
/** Helper for sending boolean replies to dbus method calls * * Reply will not be sent if no_reply attribute is set * in the method call message. * * @param msg method call message to reply * @param value integer number to send * * @return TRUE on success, or FALSE if reply could not be sent */ static gboolean cpu_keepalive_reply_int(DBusMessage *const msg, gint value) { gboolean success = TRUE; if( !dbus_message_get_no_reply(msg) ) { dbus_int32_t data = value; DBusMessage *reply = dbus_new_method_reply(msg); dbus_message_append_args(reply, DBUS_TYPE_INT32, &data, DBUS_TYPE_INVALID); /* dbus_send_message() unrefs the message */ success = dbus_send_message(reply), reply = 0; if( !success ) { mce_log(LL_WARN, "failed to send reply to %s", dbus_message_get_member(msg)); } } return success; }
/** Helper for sending boolean replies to dbus method calls * * Reply will not be sent if no_reply attribute is set * in the method call message. * * @param msg method call message to reply * @param value TRUE/FALSE to send * * @return TRUE on success, or FALSE if reply could not be sent */ static gboolean cka_dbusutil_reply_bool(DBusMessage *const msg, gboolean value) { gboolean success = TRUE; if( !dbus_message_get_no_reply(msg) ) { dbus_bool_t data = value; DBusMessage *reply = dbus_new_method_reply(msg); dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &data, DBUS_TYPE_INVALID); /* dbus_send_message() unrefs the message */ success = dbus_send_message(reply), reply = 0; if( !success ) { mce_log(LL_WARN, "failed to send reply to %s", dbus_message_get_member(msg)); } } return success; }
/** D-Bus callback for the get color profile ids method call * * @param msg The D-Bus message * @return TRUE */ static gboolean color_profile_ids_get_req_dbus_cb(DBusMessage *const msg) { mce_log(LL_DEVEL, "Received list color profiles request from %s", mce_dbus_get_message_sender_ident(msg)); DBusMessage *rsp = 0; int cnt = sizeof color_profiles / sizeof *color_profiles; const char * const * vec = color_profiles; if( dbus_message_get_no_reply(msg) ) goto EXIT; if( !(rsp = dbus_message_new_method_return(msg)) ) goto EXIT; if( !dbus_message_append_args(rsp, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &vec, cnt, DBUS_TYPE_INVALID) ) goto EXIT; dbus_send_message(rsp), rsp = 0; EXIT: if( rsp ) dbus_message_unref(rsp); return TRUE; }
/** * D-Bus callback for the remove activity callback method call * * @param msg The D-Bus message * @return TRUE on success, FALSE on failure */ static gboolean remove_activity_callback_dbus_cb(DBusMessage *const msg) { dbus_bool_t no_reply = dbus_message_get_no_reply(msg); const gchar *sender = dbus_message_get_sender(msg); gboolean status = FALSE; if (sender == NULL) { mce_log(LL_ERR, "Received invalid remove activity callback request " "(sender == NULL)"); goto EXIT; } mce_log(LL_DEVEL, "Received remove activity callback request from %s", mce_dbus_get_name_owner_ident(sender)); status = TRUE; remove_activity_cb(sender); EXIT: if (no_reply == FALSE) { DBusMessage *reply = dbus_new_method_reply(msg); status = dbus_send_message(reply); } else { status = TRUE; } return status; }
/** * D-Bus callback for the version get method call * * @param msg The D-Bus message to reply to * @return TRUE on success, FALSE on failure */ static gboolean version_get_dbus_cb(DBusMessage *const msg) { static const gchar *const versionstring = G_STRINGIFY(PRG_VERSION); DBusMessage *reply = NULL; gboolean status = FALSE; mce_log(LL_DEBUG, "Received version information request"); /* Create a reply */ reply = dbus_new_method_reply(msg); /* Append the version information */ if (dbus_message_append_args(reply, DBUS_TYPE_STRING, &versionstring, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append reply argument to D-Bus message " "for %s.%s", MCE_REQUEST_IF, MCE_VERSION_GET); dbus_message_unref(reply); goto EXIT; } /* Send the message */ status = dbus_send_message(reply); EXIT: return status; }
/** * D-Bus callback for the ALS disabling method call * * @param msg The D-Bus message * @return TRUE */ static gboolean als_disable_req_dbus_cb(DBusMessage *const msg) { const char *sender; gssize retval; if( !(sender = dbus_message_get_sender(msg)) ) goto EXIT; mce_log(LL_DEBUG, "Received ALS disable request from %s", sender); retval = mce_dbus_owner_monitor_remove(sender, &ext_als_enablers); if (retval == -1) { mce_log(LL_INFO, "Failed to remove name owner monitoring" " for `%s'",sender); goto EXIT; } rethink_als_status(); EXIT: if( !dbus_message_get_no_reply(msg) ) { DBusMessage *reply = dbus_new_method_reply(msg); dbus_send_message(reply), reply = 0; } return TRUE; }
int systemd_start_unit(struct container *ct, int pid) { static const char *mode = "fail"; char *slice = "system.slice"; char unit_name[PATH_MAX], *name = unit_name; char desc[1024], *pdesc = desc; dbus_bool_t yes = true; DBusConnection *conn; DBusMessage *msg, *reply; DBusMessageIter args, props, aux; if (ct->slice) slice = ct->slice; snprintf(unit_name, sizeof(unit_name), "%s-%s.scope", slice, ct->name); snprintf(desc, sizeof(desc), "docker container %s", ct->name); msg = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (!msg) { pr_err("can't allocate new method call"); return -1; } dbus_message_append_args(msg, 's', &name, 's', &mode, 0); dbus_message_iter_init_append(msg, &args); dbus_message_iter_open_container(&args, 'a', "(sv)", &props); set_property(&props, "Description", 's', &pdesc); set_property(&props, "Slice", 's', &slice); set_property(&props, "MemoryAccounting", 'b', &yes); set_property(&props, "CPUAccounting", 'b', &yes); set_property(&props, "BlockIOAccounting", 'b', &yes); set_pid(&props, pid); dbus_message_iter_close_container(&args, &props); dbus_message_iter_open_container(&args, 'a', "(sa(sv))", &aux); dbus_message_iter_close_container(&args, &aux); conn = get_connection(DBUS_BUS_SYSTEM); if (conn == NULL) return -1; reply = dbus_send_message(conn, msg); dbus_message_unref(msg); if (reply == NULL) return -1; dbus_message_unref(reply); return 0; }
/** * Send the call state and type * * @param method_call A DBusMessage to reply to; * pass NULL to send a signal instead * @param call_state A string representation of an alternate state * to send instead of the real call state * @param call_type A string representation of an alternate type * to send instead of the real call type * @return TRUE on success, FALSE on failure */ static gboolean send_call_state(DBusMessage *const method_call, const gchar *const call_state, const gchar *const call_type) { DBusMessage *msg = NULL; gboolean status = FALSE; const gchar *sstate; const gchar *stype; /* Allow spoofing */ if (call_state != NULL) sstate = call_state; else sstate = call_state_repr(datapipe_get_gint(call_state_pipe)); if (call_type != NULL) stype = call_type; else stype = call_type_repr(datapipe_get_gint(call_type_pipe)); /* If method_call is set, send a reply, * otherwise, send a signal */ if (method_call != NULL) { msg = dbus_new_method_reply(method_call); } else { /* sig_call_state_ind */ msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_CALL_STATE_SIG); } /* Append the call state and call type */ if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &sstate, DBUS_TYPE_STRING, &stype, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append %sarguments to D-Bus message " "for %s.%s", method_call ? "reply " : "", method_call ? MCE_REQUEST_IF : MCE_SIGNAL_IF, method_call ? MCE_CALL_STATE_GET : MCE_CALL_STATE_SIG); dbus_message_unref(msg); goto EXIT; } /* Send the message */ status = dbus_send_message(msg); EXIT: return status; }
/** * Generic function to send D-Bus messages and signals * to send a signal, call dbus_send with service == NULL * * @todo Make it possible to send D-Bus replies as well * * @param service D-Bus service; for signals, set to NULL * @param path D-Bus path * @param interface D-Bus interface * @param name The D-Bus method or signal name to send to * @param callback A reply callback, or NULL to set no reply; * for signals, this is unused, but please use NULL * for consistency * @param first_arg_type The DBUS_TYPE of the first argument in the list * @param ... The arguments to append to the D-Bus message; * terminate with DBUS_TYPE_INVALID * Note: the arguments MUST be passed by reference * @return TRUE on success, FALSE on failure */ gboolean dbus_send(const gchar *const service, const gchar *const path, const gchar *const interface, const gchar *const name, DBusPendingCallNotifyFunction callback, int first_arg_type, ...) { DBusMessage *msg; gboolean status = FALSE; va_list var_args; if (service != NULL) { msg = dbus_new_method_call(service, path, interface, name); if (callback == NULL) dbus_message_set_no_reply(msg, TRUE); } else { if (callback != NULL) { mce_log(LL_ERR, "Programmer snafu! " "dbus_send() called with a DBusPending " "callback for a signal. Whoopsie!"); callback = NULL; } msg = dbus_new_signal(path, interface, name); } /* Append the arguments, if any */ va_start(var_args, first_arg_type); if (first_arg_type != DBUS_TYPE_INVALID) { if (dbus_message_append_args_valist(msg, first_arg_type, var_args) == FALSE) { mce_log(LL_CRIT, "Failed to append arguments to D-Bus message " "for %s.%s", interface, name); dbus_message_unref(msg); goto EXIT; } } /* Send the signal / call the method */ if (callback == NULL) { status = dbus_send_message(msg); } else { status = dbus_send_message_with_reply_handler(msg, callback); } EXIT: va_end(var_args); return status; }
/** Send an inactivity status reply or signal * * @param method_call A DBusMessage to reply to; * pass NULL to send an inactivity status signal instead * @return TRUE */ static gboolean mia_dbus_send_inactivity_state(DBusMessage *const method_call) { /* Make sure initial state is broadcast; -1 does not match TRUE/FALSE */ static int last_sent = -1; DBusMessage *msg = NULL; if( method_call ) { /* Send reply to state query */ msg = dbus_new_method_reply(method_call); } else if( last_sent == device_inactive ) { /* Do not repeat broadcasts */ goto EXIT; } else { /* Broadcast state change */ #ifdef ENABLE_WAKELOCKS /* Block suspend for a while to give other processes * a chance to get and process the signal. */ mia_keepalive_start(); #endif msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_INACTIVITY_SIG); } mce_log(method_call ? LL_DEBUG : LL_DEVEL, "Sending inactivity %s: %s", method_call ? "reply" : "signal", mia_inactivity_repr(device_inactive)); /* Append the inactivity status */ if( !dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &device_inactive, DBUS_TYPE_INVALID) ) { mce_log(LL_ERR, "Failed to append argument to D-Bus message"); goto EXIT; } /* Send the message */ dbus_send_message(msg), msg = 0; if( !method_call ) last_sent = device_inactive; EXIT: if( msg ) dbus_message_unref(msg); return TRUE; }
/** Send the radio states * * @param method_call A DBusMessage to reply to; * pass NULL to send a signal instead * * @return TRUE on success, FALSE on failure */ static gboolean mrs_dbus_send_radio_states(DBusMessage *const method_call) { static dbus_uint32_t prev = ~0u; DBusMessage *msg = NULL; gboolean status = FALSE; dbus_uint32_t data = active_radio_states; if( method_call ) { /* Send reply to a method call */ msg = dbus_new_method_reply(method_call); } else if( prev == data ) { /* Skip duplicate signals */ goto EXIT; } else { /* Broadcast change signal */ prev = data; msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_RADIO_STATES_SIG); } mce_log(LL_DEBUG, "Sending radio states %s: %s", method_call ? "reply" : "signal", radio_states_repr(data)); /* Append the radio states */ if (dbus_message_append_args(msg, DBUS_TYPE_UINT32, &data, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append %sargument to D-Bus message " "for %s.%s", method_call ? "reply " : "", method_call ? MCE_REQUEST_IF : MCE_SIGNAL_IF, method_call ? MCE_RADIO_STATES_GET : MCE_RADIO_STATES_SIG); dbus_message_unref(msg); goto EXIT; } /* Send the message */ status = dbus_send_message(msg); EXIT: return status; }
dbus_bool_t dbus_send_error_valist(DBusConnection *connection, DBusMessage *message, const char *name, const char *format, va_list args) { DBusMessage *error; char str[1024]; vsnprintf(str, sizeof(str), format, args); error = dbus_message_new_error(message, name, str); if (error == NULL) return FALSE; return dbus_send_message(connection, error); }
/** D-Bus callback for the add activity callback method call * * @param req The D-Bus message * * @return TRUE */ static gboolean mia_dbus_add_activity_action_cb(DBusMessage *const req) { const char *sender = dbus_message_get_sender(req); DBusError err = DBUS_ERROR_INIT; const char *service = 0; const char *path = 0; const char *interface = 0; const char *method = 0; dbus_bool_t res = false; if( !sender ) goto EXIT; mce_log(LL_DEVEL, "Add activity callback request from %s", mce_dbus_get_name_owner_ident(sender)); if( !dbus_message_get_args(req, &err, DBUS_TYPE_STRING, &service, DBUS_TYPE_STRING, &path, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &method, DBUS_TYPE_INVALID) ) { mce_log(LL_ERR, "Failed to get arguments: %s: %s", err.name, err.message); goto EXIT; } res = mia_activity_action_add(sender, service, path, interface, method); EXIT: if( !dbus_message_get_no_reply(req) ) { DBusMessage *rsp = dbus_new_method_reply(req); if( !dbus_message_append_args(rsp, DBUS_TYPE_BOOLEAN, &res, DBUS_TYPE_INVALID) ) { mce_log(LL_ERR, "Failed to append reply argument"); dbus_message_unref(rsp); } else { dbus_send_message(rsp); } } dbus_error_free(&err); return TRUE; }
dbus_bool_t dbus_send_reply_valist(DBusConnection *connection, DBusMessage *message, int type, va_list args) { DBusMessage *reply; reply = dbus_message_new_method_return(message); if (reply == NULL) return FALSE; if (dbus_message_append_args_valist(reply, type, args) == FALSE) { dbus_message_unref(reply); return TRUE; } return dbus_send_message(connection, reply); }
/** * Send an inactivity status reply or signal * * @param method_call A DBusMessage to reply to; * pass NULL to send an inactivity status signal instead * @return TRUE on success, FALSE on failure */ static gboolean send_inactivity_status(DBusMessage *const method_call) { DBusMessage *msg = NULL; gboolean status = FALSE; mce_log(LL_DEBUG, "Sending inactivity status: %s", device_inactive ? "inactive" : "active"); /* If method_call is set, send a reply, * otherwise, send a signal */ if (method_call != NULL) { msg = dbus_new_method_reply(method_call); } else { /* system_inactivity_ind */ msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_INACTIVITY_SIG); } /* Append the inactivity status */ if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &device_inactive, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append %sargument to D-Bus message " "for %s.%s", method_call ? "reply " : "", method_call ? MCE_REQUEST_IF : MCE_SIGNAL_IF, method_call ? MCE_INACTIVITY_STATUS_GET : MCE_INACTIVITY_SIG); dbus_message_unref(msg); goto EXIT; } /* Send the message */ status = dbus_send_message(msg); EXIT: return status; }
/** * Send the PSM state * * @param method_call A DBusMessage to reply to; * pass NULL to send a signal instead * @return TRUE on success, FALSE on failure */ static gboolean send_psm_state(DBusMessage *const method_call) { DBusMessage *msg = NULL; gboolean status = FALSE; mce_log(LL_DEBUG, "Sending PSM state: %s", active_power_saving_mode ? "TRUE" : "FALSE"); /* If method_call is set, send a reply, * otherwise, send a signal */ if (method_call != NULL) { msg = dbus_new_method_reply(method_call); } else { /* psm_state_ind */ msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_PSM_STATE_SIG); } /* Append the power saving mode */ if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &active_power_saving_mode, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append %sargument to D-Bus message " "for %s.%s", method_call ? "reply " : "", method_call ? MCE_REQUEST_IF : MCE_SIGNAL_IF, method_call ? MCE_PSM_STATE_GET : MCE_PSM_STATE_SIG); dbus_message_unref(msg); goto EXIT; } /* Send the message */ status = dbus_send_message(msg); EXIT: return status; }
/** D-Bus callback for the remove activity callback method call * * @param req The D-Bus message * * @return TRUE */ static gboolean mia_dbus_remove_activity_action_cb(DBusMessage *const req) { const char *sender = dbus_message_get_sender(req); if( !sender ) goto EXIT; mce_log(LL_DEVEL, "Remove activity callback request from %s", mce_dbus_get_name_owner_ident(sender)); mia_activity_action_remove(sender); EXIT: if( !dbus_message_get_no_reply(req) ) { DBusMessage *reply = dbus_new_method_reply(req); dbus_send_message(reply); } return TRUE; }
/** D-Bus callback for the color profile change method call * * @param msg The D-Bus message * @return TRUE */ static gboolean color_profile_change_req_dbus_cb(DBusMessage *const msg) { mce_log(LL_DEVEL, "Received set color profile request from %s", mce_dbus_get_message_sender_ident(msg)); const char *val = 0; DBusError err = DBUS_ERROR_INIT; dbus_bool_t ack = FALSE; DBusMessage *rsp = 0; if( !dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &val, DBUS_TYPE_INVALID)) { // XXX: should we return an error instead? mce_log(LL_ERR, "Failed to get argument from %s.%s: %s: %s", MCE_REQUEST_IF, MCE_COLOR_PROFILE_CHANGE_REQ, err.name, err.message); } else { if( set_color_profile(val) ) ack = TRUE; } if( dbus_message_get_no_reply(msg) ) goto EXIT; if( !(rsp = dbus_message_new_method_return(msg)) ) goto EXIT; dbus_message_append_args(rsp, DBUS_TYPE_BOOLEAN, &ack, DBUS_TYPE_INVALID); EXIT: if( rsp ) dbus_send_message(rsp), rsp = 0; dbus_error_free(&err); return TRUE; }
/** D-Bus callback for radio states change method call * * @todo Decide on error handling policy * * @param msg The D-Bus message * * @return TRUE on success, FALSE on failure */ static gboolean mrs_dbus_set_radio_states_cb(DBusMessage *const msg) { dbus_bool_t no_reply = dbus_message_get_no_reply(msg); gboolean status = FALSE; dbus_uint32_t states = 0; dbus_uint32_t mask = 0; DBusError error = DBUS_ERROR_INIT; mce_log(LL_DEVEL, "Received radio states change request from %s", mce_dbus_get_message_sender_ident(msg)); if (dbus_message_get_args(msg, &error, DBUS_TYPE_UINT32, &states, DBUS_TYPE_UINT32, &mask, DBUS_TYPE_INVALID) == FALSE) { // XXX: should we return an error instead? mce_log(LL_CRIT, "Failed to get argument from %s.%s: %s", MCE_REQUEST_IF, MCE_RADIO_STATES_CHANGE_REQ, error.message); goto EXIT; } mrs_modify_radio_states(states, mask); if (no_reply == FALSE) { DBusMessage *reply = dbus_new_method_reply(msg); status = dbus_send_message(reply); } else { status = TRUE; } EXIT: dbus_error_free(&error); return status; }
/** D-Bus callback for the get memory level method call * * @param msg The D-Bus message * * @return TRUE */ static gboolean memnotify_dbus_get_level_cb(DBusMessage *const req) { mce_log(LL_DEVEL, "Received memory leve get request from %s", mce_dbus_get_message_sender_ident(req)); DBusMessage *rsp = dbus_new_method_reply(req); const char *arg = memnotify_level_name(memnotify_level); if( !dbus_message_append_args(rsp, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID) ) goto EXIT; mce_log(LL_DEBUG, "sending memory level reply: %s", arg); dbus_send_message(rsp), rsp = 0; EXIT: if( rsp ) dbus_message_unref(rsp); return TRUE; }
/** * D-Bus callback for powerkey event triggering * * @param msg D-Bus message * @return TRUE on success, FALSE on failure */ static gboolean trigger_powerkey_event_req_dbus_cb(DBusMessage *const msg) { dbus_bool_t no_reply = dbus_message_get_no_reply(msg); DBusMessageIter iter; dbus_uint32_t uintval; dbus_bool_t boolval; gint argcount = 0; gint argtype; gboolean status = FALSE; DBusError error; /* Register error channel */ dbus_error_init(&error); mce_log(LL_DEBUG, "Received [power] button trigger request"); if (dbus_message_iter_init(msg, &iter) == FALSE) { // XXX: should we return an error instead? mce_log(LL_ERR, "Failed to initialise D-Bus message iterator; " "message has no arguments"); goto EXIT; } argtype = dbus_message_iter_get_arg_type(&iter); argcount++; switch (argtype) { case DBUS_TYPE_BOOLEAN: dbus_message_iter_get_basic(&iter, &boolval); uintval = (boolval == TRUE) ? 1 : 0; break; case DBUS_TYPE_UINT32: dbus_message_iter_get_basic(&iter, &uintval); if (uintval > 2) { mce_log(LL_ERR, "Incorrect powerkey event passed to %s.%s; " "ignoring request", MCE_REQUEST_IF, MCE_TRIGGER_POWERKEY_EVENT_REQ); goto EXIT; } break; default: mce_log(LL_ERR, "Argument %d passed to %s.%s has incorrect type", argcount, MCE_REQUEST_IF, MCE_TRIGGER_POWERKEY_EVENT_REQ); goto EXIT; } while (dbus_message_iter_next(&iter) == TRUE) argcount++; if (argcount > 1) { mce_log(LL_WARN, "Too many arguments passed to %s.%s; " "got %d, expected %d -- ignoring extra arguments", MCE_REQUEST_IF, MCE_TRIGGER_POWERKEY_EVENT_REQ, argcount, 1); } mce_log(LL_DEBUG, "[power] button event trigger value: %d", uintval); cancel_powerkey_timeout(); cancel_doublepress_timeout(); switch (uintval) { default: case 0: /* short press */ generic_powerkey_handler(shortpressaction, shortpresssignal); break; case 1: /* long press */ handle_longpress(); break; case 2: /* double press */ generic_powerkey_handler(doublepressaction, doublepresssignal); break; } if (no_reply == FALSE) { DBusMessage *reply = dbus_new_method_reply(msg); status = dbus_send_message(reply); } else { status = TRUE; } EXIT: return status; }
/** * D-Bus callback for the call state change request method call * * @param msg The D-Bus message * @return TRUE on success, FALSE on failure */ static gboolean change_call_state_dbus_cb(DBusMessage *const msg) { gboolean status = FALSE; const char *state = 0; const char *type = 0; const gchar *sender = dbus_message_get_sender(msg); call_state_t call_state = CALL_STATE_NONE; call_type_t call_type = NORMAL_CALL; DBusMessage *reply = NULL; DBusError error = DBUS_ERROR_INIT; dbus_bool_t changed = false; mce_log(LL_DEBUG, "Received set call state request"); if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &state, DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID) == FALSE) { // XXX: return an error! mce_log(LL_CRIT, "Failed to get argument from %s.%s: %s", MCE_REQUEST_IF, MCE_CALL_STATE_CHANGE_REQ, error.message); dbus_error_free(&error); goto EXIT; } /* Convert call state to enum */ call_state = call_state_parse(state); if (call_state == MCE_INVALID_TRANSLATION) { mce_log(LL_DEBUG, "Invalid call state received; request ignored"); goto EXIT; } /* Convert call type to enum */ call_type = call_type_parse(type); if (call_type == MCE_INVALID_TRANSLATION) { mce_log(LL_DEBUG, "Invalid call type received; request ignored"); goto EXIT; } /* reject no-call emergency calls ... */ if( call_state == CALL_STATE_NONE ) call_type = NORMAL_CALL; /* If call state isn't monitored or if the request comes from * the owner of the current state, then some additional changes * are ok */ if( call_state_monitor_list && !mce_dbus_is_owner_monitored(sender, call_state_monitor_list) ) { mce_log(LL_DEBUG, "Call state already has owner; ignoring request"); goto EXIT; } /* Only transitions to/from "none" are allowed, * and from "ringing" to "active", * to avoid race conditions; except when new tuple * is active:emergency */ if( call_state == CALL_STATE_ACTIVE && simulated.state != CALL_STATE_RINGING && call_type != EMERGENCY_CALL ) { mce_log(LL_INFO, "Call state change vetoed. Requested: %i:%i " "(current: %i:%i)", call_state, call_type, simulated.state, simulated.type); goto EXIT; } if( call_state != CALL_STATE_NONE && mce_dbus_owner_monitor_add(sender, call_state_owner_monitor_dbus_cb, &call_state_monitor_list, 1) != -1 ) { simulated.state = call_state; simulated.type = call_type; } else { mce_dbus_owner_monitor_remove(sender, &call_state_monitor_list); simulated.state = CALL_STATE_NONE; simulated.type = NORMAL_CALL; } changed = call_state_rethink_forced(); EXIT: /* Setup the reply */ reply = dbus_new_method_reply(msg); /* Append the result */ if (dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &changed, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append reply arguments to D-Bus " "message for %s.%s", MCE_REQUEST_IF, MCE_CALL_STATE_CHANGE_REQ); dbus_message_unref(reply); } else { /* Send the message */ status = dbus_send_message(reply); } return status; }
/** * D-Bus callback for the add activity callback method call * * @param msg The D-Bus message * @return TRUE on success, FALSE on failure */ static gboolean add_activity_callback_dbus_cb(DBusMessage *const msg) { dbus_bool_t no_reply = dbus_message_get_no_reply(msg); const gchar *sender = dbus_message_get_sender(msg); const gchar *service = NULL; const gchar *path = NULL; const gchar *interface = NULL; const gchar *method_name = NULL; activity_cb_t *tmp = NULL; gboolean result = FALSE; gboolean status = FALSE; DBusError error; /* Register error channel */ dbus_error_init(&error); if (sender == NULL) { mce_log(LL_ERR, "Received invalid add activity callback request " "(sender == NULL)"); goto EXIT; } mce_log(LL_DEVEL, "Received add activity callback request from %s", mce_dbus_get_name_owner_ident(sender)); /* Extract result */ if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &service, DBUS_TYPE_STRING, &path, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &method_name, DBUS_TYPE_INVALID) == FALSE) { // XXX: should we return an error instead? mce_log(LL_CRIT, "Failed to get argument from %s.%s; %s", MCE_REQUEST_IF, MCE_ADD_ACTIVITY_CALLBACK_REQ, error.message); dbus_error_free(&error); goto EXIT; } if (mce_dbus_owner_monitor_add(sender, activity_cb_monitor_dbus_cb, &activity_cb_monitor_list, ACTIVITY_CB_MAX_MONITORED) == -1) { mce_log(LL_ERR, "Failed to add name owner monitoring for `%s'", sender); goto EXIT2; } tmp = g_malloc(sizeof (activity_cb_t)); tmp->owner = g_strdup(sender); tmp->service = g_strdup(service); tmp->path = g_strdup(path); tmp->interface = g_strdup(interface); tmp->method_name = g_strdup(method_name); activity_callbacks = g_slist_prepend(activity_callbacks, tmp); result = TRUE; EXIT2: if (no_reply == FALSE) { DBusMessage *reply = dbus_new_method_reply(msg); if (dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append reply argument to " "D-Bus message for %s.%s", MCE_REQUEST_IF, MCE_ADD_ACTIVITY_CALLBACK_REQ); dbus_message_unref(reply); goto EXIT; } status = dbus_send_message(reply); } else { status = TRUE; } EXIT: return status; }