diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-04-15 17:53:42 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-04-15 17:53:42 -0500 |
commit | 3c32b869c2208758c2027d094c8930592370858a (patch) | |
tree | 39724674d33faf4a09f28fce507c7ccbbf79a9a3 /src/dbusInterface.cpp | |
parent | 3ec8230e9f10645de684b5e03471e293481183d7 (diff) | |
download | tdepowersave-3c32b869c2208758c2027d094c8930592370858a.tar.gz tdepowersave-3c32b869c2208758c2027d094c8930592370858a.zip |
Rename dbusHAL class to something more sensible
Diffstat (limited to 'src/dbusInterface.cpp')
-rw-r--r-- | src/dbusInterface.cpp | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/src/dbusInterface.cpp b/src/dbusInterface.cpp new file mode 100644 index 0000000..adec4cd --- /dev/null +++ b/src/dbusInterface.cpp @@ -0,0 +1,648 @@ + /************************************************************************** + * Copyright (C) 2006-2007 by Danny Kukawka * + * <dkukawka@suse.de>, <danny.kukawka@web.de> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of version 2 of the GNU General Public License * + * as published by the Free Software Foundation. * + * * + * 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. * + ***************************************************************************/ + +/*! + * \file dbusInterface.cpp + * \brief In this file can be found the functionality to connect to + * the HAL daemon via D-Bus, to handle D-Bus calls/events and to + * provide wrapper to HAL lib and functions + * \author Danny Kukawka, <dkukawka@suse.de>, <danny.kukawka@web.de> + * \date 2006-2007 + */ + + // KDE Header +#include <klocale.h> + +// DBUS - Header +#include "dbusInterface.h" + +// system headers +#include <iostream> + +static void* myInstance = 0; + +/*! The default constructor of the class dbusInterface. */ +dbusInterface::dbusInterface(){ + kdDebugFuncIn(trace); + + dbus_is_connected = false; + aquiredPolicyPower = false; + + // add pointer to this for filter_function() + myInstance=this; + // init connection to dbus + if(!initDBUS()) { + kdError() << "Can't connect to D-Bus" << endl; + m_dBusQtConnection = NULL; + } + + kdDebugFuncOut(trace); +} + +/*! This is the default destructor of class dbusPowersaveConnection. */ +dbusInterface::~dbusInterface(){ + kdDebugFuncIn(trace); + + close(); + myInstance = NULL; + + kdDebugFuncOut(trace); +} + +/*! + * This function return information about connection status to the DBUS daemon. + * \return boolean with the state of the connection to D-Bus + * \retval true if connected + * \retval false if disconnected + */ +bool dbusInterface::isConnectedToDBUS() { + return dbus_is_connected; +} + +/*! + * This function return information if the org.freedesktop.Policy.Power + * interface was claimed. + * \return boolean with the status of claim the interface + * \retval true if aquired + * \retval false if not + */ +bool dbusInterface::aquiredPolicyPowerInterface() { + return aquiredPolicyPower; +} + +/*! + * This function try a reconnect to D-Bus and HAL daemon. + * \return boolean with the result of the operation + * \retval true if successful reconnected to D-Bus and HAL + * \retval false if unsuccessful + */ +bool dbusInterface::reconnect() { + // close D-Bus connection + close(); + // init D-Bus conntection and HAL context + return (initDBUS()); +} + +/*! + * This function close the connection to powersave over the D-Bus daemon. + * \return boolean with the result of the operation + * \retval true if successful closed the connection + * \retval false if any problems + */ +bool dbusInterface::close() { + if ( m_dBusQtConnection != NULL ) { + releasePolicyPowerIface(); + m_dBusQtConnection->close(); + m_dBusQtConnection = NULL; + } + dbus_is_connected = false; + + return true; +} + +/* ----> D-Bus section :: START <---- */ + +/*! + * This function initialise the connection to the D-Bus daemon. + * \return boolean with the result of the operation + * \retval true if successful initialised D-Bus connection + * \retval false if unsuccessful + */ +bool dbusInterface::initDBUS(){ + kdDebugFuncIn(trace); + + dbus_is_connected = false; + + DBusError error; + dbus_error_init(&error); + + dbus_connection = dbus_bus_get( DBUS_BUS_SYSTEM, &error ); + + if (dbus_connection == NULL){ + kdError() << "Failed to open connection to system message bus: " << error.message << endl; + dbus_error_free (&error); + return false; + } + + if ( dbus_error_is_set( &error ) ) { + kdError() << "Failed to register connection with system message bus: " << error.message << endl; + return false; + } + + aquirePolicyPowerIface(); + + dbus_connection_set_exit_on_disconnect( dbus_connection, false ); + + /* add the filter function which should be executed on events on the bus */ + if ( ! dbus_connection_add_filter( dbus_connection, filterFunction, this, NULL) ) { + kdFatal() << "Error: Not enough memory to add filter to dbus connection" << endl; + exit(EXIT_FAILURE); + } + + /* add a match rule to catch all signals going through the bus with D-Bus interface */ + dbus_bus_add_match( dbus_connection, "type='signal'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'", NULL); + + /* add a match rule to catch all signals going through the bus with ConsoleKit Interface */ + dbus_bus_add_match( dbus_connection, "type='signal'," + "interface='org.freedesktop.ConsoleKit.Session'," + "member='ActiveChanged'", NULL); + + m_dBusQtConnection = new DBusQt::Connection(this); + m_dBusQtConnection->dbus_connection_setup_with_qt_main(dbus_connection); + + dbus_is_connected = true; + + kdDebugFuncOut(trace); + return true; +} + +/*! + * This function aquire the org.freedesktop.Policy.Power interface + * \return boolean with the result of the operation + * \retval true if successful aquired the interface + * \retval false if unsuccessful + */ +bool dbusInterface::aquirePolicyPowerIface(){ + kdDebugFuncIn(trace); + + if (dbus_connection == NULL) { + kdDebugFuncOut(trace); + return false; + } + + switch (dbus_bus_request_name(dbus_connection, "org.freedesktop.Policy.Power", + DBUS_NAME_FLAG_REPLACE_EXISTING, NULL)) { + case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: + kdDebug() << "Acquired org.freedesktop.Policy.Power interface" << endl; + aquiredPolicyPower = true; + break; + case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: + kdWarning() << "Queued to aquire org.freedesktop.Policy.Power interface" << endl; + aquiredPolicyPower = false; + break; + default: + kdWarning() << "Unknown error while aquire org.freedesktop.Policy.Power interface" << endl; + aquiredPolicyPower = false; + break; + } + + kdDebugFuncOut(trace); + return aquiredPolicyPower; +} + +/*! + * This function release the org.freedesktop.Policy.Power interface + * \return boolean with the result of the operation + * \retval true if successful aquired the interface + * \retval false if unsuccessful + */ +bool dbusInterface::releasePolicyPowerIface(){ + kdDebugFuncIn(trace); + + int result; + bool retval = false; + DBusError error; + + if (dbus_connection == NULL) { + kdDebugFuncOut(trace); + return false; + } + + dbus_error_init(&error); + + result = dbus_bus_release_name(dbus_connection, "org.freedesktop.Policy.Power", &error); + + if ( dbus_error_is_set( &error ) ) { + kdError() << "Failed to release org.freedesktop.Policy.Power: " << error.message << endl; + dbus_error_free(&error); + } else { + switch (result) { + case DBUS_RELEASE_NAME_REPLY_RELEASED: + kdDebug() << "Released org.freedesktop.Policy.Power interface" << endl; + retval = true; + aquiredPolicyPower = false; + break; + case DBUS_RELEASE_NAME_REPLY_NOT_OWNER: + kdWarning() << "Couldn't release org.freedesktop.Policy.Power, not the owner" << endl; + break; + case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT: + kdWarning() << "Couldn't release org.freedesktop.Policy.Power, Iface not existing" << endl; + break; + default: + kdWarning() << "Couldn't release org.freedesktop.Policy.Power, unknown error" << endl; + break; + } + } + + return retval; + kdDebugFuncOut(trace); +} + +/*! + * This function check if the org.freedesktop.Policy.Power + * interface is owned by someone + * \return boolean with the result of the operation + * \retval true if the interface is owned by someone + * \retval false if else + */ +bool dbusInterface::isPolicyPowerIfaceOwned(){ + kdDebugFuncIn(trace); + + bool retval = false; + DBusError error; + + if (dbus_connection == NULL) { + kdDebugFuncOut(trace); + return false; + } + + dbus_error_init(&error); + + retval = dbus_bus_name_has_owner(dbus_connection, "org.freedesktop.Policy.Power", &error); + + if ( dbus_error_is_set( &error ) ) { + kdError() << "Failed to check if org.freedesktop.Policy.Power has an owner: " << error.message << endl; + dbus_error_free(&error); + } + + kdDebugFuncOut(trace); + return retval; +} + +/* ----> DBUS section :: END <---- */ + +/* ----> D-Bus methode calls functions :: START <---- */ +/*! + * This function call a D-Bus method + * \param interface TQString with te dbus interface + * \param path TQString with the object path + * \param object TQString with the object name + * \param method TQString with the name of the methode + * \param first_arg_type integer with the dbus type of the first argument + * \param ... more arguments + * \return If the query was successful or not + */ +bool dbusInterface::dbusSystemMethodCall( TQString interface, TQString path, TQString object, TQString method, + int first_arg_type, ... ) { + kdDebugFuncIn(trace); + + bool _ret = false; + va_list var_args; + + va_start(var_args, first_arg_type); + _ret = dbusMethodCall( interface, path, object, method, DBUS_BUS_SYSTEM, + NULL, -1, first_arg_type, var_args); + va_end(var_args); + + kdDebugFuncOut(trace); + return _ret; +} + + +/*! + * This overloaded function call a D-Bus method on the D-Bus system bus with a return value + * \param interface TQString with the dbus interface + * \param path TQString with the object path + * \param object TQString with the object name + * \param method TQString with the name of the method + * \param retvalue void pointer to arguments, if NULL we make a simple call + * \param retval_type Integer with the dbus type of the return value, set to -1 if retvalue is NULL + * \param first_arg_type Integer with the dbus type of the first argument followed by the value + * \return If the query was successful or not + */ +bool dbusInterface::dbusSystemMethodCall( TQString interface, TQString path, TQString object, TQString method, + void *retvalue, int retval_type, int first_arg_type, ... ) { + kdDebugFuncIn(trace); + + bool _ret = false; + va_list var_args; + + va_start(var_args, first_arg_type); + _ret = dbusMethodCall( interface, path, object, method, DBUS_BUS_SYSTEM, + retvalue, retval_type, first_arg_type, var_args); + va_end(var_args); + + kdDebugFuncOut(trace); + return _ret; +} + + +/*! + * This function call a D-Bus method with a return value + * \param interface TQString with the dbus interface + * \param path TQString with the object path + * \param object TQString with the object name + * \param method TQString with the name of the method + * \param dbus_type DBusBusType with the D-Bus BUS Type + * \param retvalue void pointer to arguments, if NULL we make a simple call + * \param retval_type Integer with the dbus type of the return value, set to -1 if retvalue is NULL + * \param first_arg_type Integer with the dbus type of the first argument followed by the value + * \param var_args va_list with more arguments + * \return If the query was successful or not + */ +bool dbusInterface::dbusMethodCall( TQString interface, TQString path, TQString object, TQString method, + DBusBusType dbus_type, void *retvalue, int retval_type, int first_arg_type, + va_list var_args ) { + kdDebugFuncIn(trace); + + DBusMessage *message; + DBusMessage *reply; + DBusError error; + bool ret = false; + + dbus_error_init(&error); + + dbus_connection = dbus_bus_get(dbus_type, &error); + + if (dbus_error_is_set(&error)) { + kdError() << "Could not get dbus connection: " << error.message << endl; + dbus_error_free(&error); + goto out; + } + + message = dbus_message_new_method_call( interface.ascii(), path.ascii(), object.ascii(), method.ascii() ); + dbus_message_append_args_valist(message, first_arg_type, var_args); + + if (retvalue == NULL) { + if (!dbus_connection_send(dbus_connection, message, NULL)) { + kdError() << "Could not send method call." << endl; + dbus_message_unref( message ); + goto out; + } + } else { + reply = dbus_connection_send_with_reply_and_block(dbus_connection, message, -1, &error); + + if (dbus_error_is_set(&error)) { + kdError() << "Could not send dbus message: " << error.message << endl; + dbus_message_unref(message); + dbus_error_free(&error); + goto out; + } + + int type = dbus_message_get_type(reply); + if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN) { + if (!dbus_message_get_args(reply, &error, retval_type, retvalue, DBUS_TYPE_INVALID)){ + if (dbus_error_is_set(&error)) { + kdError() << "Could not get argument from reply: " + << error.message << endl; + dbus_error_free(&error); + } + dbus_message_unref(reply); + dbus_message_unref(message); + goto out; + } + } else { + kdError() << "Revieved invalid DBUS_MESSAGE_TYPE: " << type + << "expected: " << DBUS_MESSAGE_TYPE_METHOD_RETURN << endl; + dbus_message_unref(reply); + dbus_message_unref(message); + goto out; + } + } + + ret = true; // if we are here, everything should be okay + dbus_message_unref(message); + dbus_connection_flush(dbus_connection); + +out: + kdDebugFuncOut(trace); + return ret; +} + +/* ----> D-Bus methode calls functions :: END <---- */ +/* ---> PolicyKit method call section :: START <--- */ + +/*! + * Check if the user is privileged to a special privilege + * \param privilege TQString with the name of the requested privilege + * \param udi TQString with the UDI. + * \param ressource TQString with the name of the ressource + * \param user TQString with the name of the user. If empty the current user is used. + * \return int with info if the user is allowed or not. + * \retval 0 if not allowed + * \retval 1 if allowed + * \retval -1 if a error occurs or we could not query the interface + */ +int dbusInterface::isUserPrivileged(TQString privilege, TQString udi, TQString ressource, TQString user) { + kdDebugFuncIn(trace); + + const char *_unique_name; + const char *_user; + const char *_privilege; + + int retval = -1; + + if (user.isEmpty() || user.isNull()) + _user = getenv("USER"); + else + _user = user.latin1(); + + if (_user == NULL || privilege.isEmpty()) + goto out; + + _unique_name = dbus_bus_get_unique_name(dbus_connection); + _privilege = privilege.latin1(); + + // not sure if we need this, but to avoid problems + dbus_bool_t _retval; + const char *_ressource; + _ressource = ressource.latin1(); + + if (!dbusSystemMethodCall( "org.freedesktop.PolicyKit", + "/org/freedesktop/PolicyKit/Manager", + "org.freedesktop.PolicyKit.Manager", + "IsUserPrivileged", + &_retval, DBUS_TYPE_BOOLEAN, + DBUS_TYPE_STRING, &_unique_name, + DBUS_TYPE_STRING, &_user, + DBUS_TYPE_STRING, &_privilege, + DBUS_TYPE_STRING, &_ressource, + DBUS_TYPE_INVALID)) { + retval = -1; // only to be sure we have no changes trough the call + } else { + retval = (int) _retval; + } + +out: + kdDebugFuncOut(trace); + return retval; +} +/* ---> PolicyKit method call section :: END <--- */ + +/*! + * Use this TQT_SLOT to emit a reviced messages to the kpowersave. + * NOTE: Because of the filter function this need to be a public function. + * Don't use this function in any other place than this class. + * \param type enum with the type of the message + * \param message String with the message + * \param string String with additional info + */ +void dbusInterface::emitMsgReceived( msg_type type, TQString message, TQString string ) { + + if (message.startsWith("dbus.terminate")) + dbus_is_connected = false; + + if (type == POLICY_POWER_OWNER_CHANGED) { + if (message.startsWith("NOW_OWNER")) + aquiredPolicyPower = true; + else + aquiredPolicyPower = false; + } + + emit msgReceived_withStringString( type, message, string ); +} + +#include "dbusInterface.moc" +// --> functions which are not member of the class ... + +/*! + * This function is needed filter function for the D-Bus connection to filter + * all needed messages from the bus which are needful for KPowersave. + * \param connection existing connection to the D-Bus daemon + * \param message the recieved message from the D-Bus daemon + * \param data void pointer (see dbus bindings for more information) + * \return DBusHandlerResult + */ +DBusHandlerResult +filterFunction (DBusConnection *connection, DBusMessage *message, void */*data*/) { + kdDebugFuncIn(trace); + + bool reply_wanted; + char *value; + TQString ifaceType; + + DBusError error; + dbus_error_init( &error ); + + if (dbus_message_is_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")){ + ((dbusInterface*) myInstance)->emitMsgReceived( DBUS_EVENT, "dbus.terminate", 0 ); + dbus_connection_unref(connection); + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if ( dbus_message_get_type( message ) != DBUS_MESSAGE_TYPE_SIGNAL ) { + if (trace) kdDebug() << "recieved message, but wasn't from type DBUS_MESSAGE_TYPE_SIGNAL" << endl; + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + ifaceType = dbus_message_get_interface( message ); + if (ifaceType == NULL) { + kdDebug() << "Received message from invalid interface" << endl; + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + reply_wanted = !dbus_message_get_no_reply( message ); + + if (ifaceType.startsWith(DBUS_INTERFACE_DBUS)) { + if(trace) kdDebug() << "Received from DBUS_INTERFACE_DBUS" << endl; + /* get the name of the signal */ + const char *signal = dbus_message_get_member( message ); + + /* get the first argument. This must be a string at the moment */ + dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID ); + + if ( dbus_error_is_set( &error ) ) { + kdWarning() << "Received signal " << error.message << " but no string argument" << endl; + dbus_error_free( &error ); + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (trace) kdDebug() << "filter_function::SIGNAL=" << signal << " VALUE=" << value << endl; + + /* our name is... */ + if ( ! strcmp( signal, "NameAcquired" ) ) { + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_HANDLED; + } + + else if ( ! strcmp( signal, "NameOwnerChanged" )) { + char *service; + char *old_owner; + char *new_owner; + + if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &service, + DBUS_TYPE_STRING, &old_owner, + DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID)) { + if (!strcmp(service, "org.freedesktop.Policy.Power")) { + const char *own_name; + + own_name = dbus_bus_get_unique_name(((dbusInterface*) myInstance)->get_DBUS_connection()); + + if (!strcmp(new_owner, own_name)) { + kdDebug() << "=== now owner of org.freedesktop.Policy.Power ===" << endl; + // we have now again the ower of the name! + ((dbusInterface*) myInstance)->emitMsgReceived( POLICY_POWER_OWNER_CHANGED, + "NOW_OWNER", + NULL ); + } else { + // some other has now the interface + kdDebug() << "=== someone owner of org.freedesktop.Policy.Power ===" << endl; + ((dbusInterface*) myInstance)->emitMsgReceived( POLICY_POWER_OWNER_CHANGED, + "OTHER_OWNER", + NULL ); + } + } + } + } + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_HANDLED; + } else if (ifaceType.startsWith("org.freedesktop.ConsoleKit.Session")) { + kdDebug() << "Received from org.freedesktop.ConsoleKit.Session" << endl; + + const char *session = dbus_message_get_path (message); + const char *signal = dbus_message_get_member( message ); + + if (! strcmp(signal, "ActiveChanged")) { + dbus_bool_t active; + + if (dbus_message_get_args( message, &error, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID )) { + ((dbusInterface*) myInstance)->emitMsgReceived( CONSOLEKIT_SESSION_ACTIVE, + session, TQString("%1").arg((int)active)); + } else { + if (dbus_error_is_set( &error )) dbus_error_free( &error ); + } + } else { + kdDebug() << "Received unknown signal from org.freedesktop.ConsoleKit.Session: " + << signal << endl; + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_HANDLED; + } else { + kdDebugFuncOut(trace); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } +} + +// --> some functions to get private members + +//! to get the current connection to D-Bus +DBusConnection * dbusInterface::get_DBUS_connection() { + return dbus_connection; +} + |