diff options
Diffstat (limited to 'lib/DBus')
-rw-r--r-- | lib/DBus/DBusManager.cpp | 203 | ||||
-rw-r--r-- | lib/DBus/DBusManager.h | 55 | ||||
-rw-r--r-- | lib/DBus/Makefile.am | 11 | ||||
-rw-r--r-- | lib/DBus/marshal.c | 51 | ||||
-rw-r--r-- | lib/DBus/marshal.h | 15 | ||||
-rw-r--r-- | lib/DBus/marshal.list | 1 | ||||
-rw-r--r-- | lib/DBus/test.cpp | 76 |
7 files changed, 412 insertions, 0 deletions
diff --git a/lib/DBus/DBusManager.cpp b/lib/DBus/DBusManager.cpp new file mode 100644 index 00000000..0b2cb97f --- /dev/null +++ b/lib/DBus/DBusManager.cpp @@ -0,0 +1,203 @@ +/* + Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) + Copyright (C) 2009 RedHat inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + */ + +#include "DBusManager.h" +#include <iostream> +#include <marshal.h> + +// only for testing - used by LoopSend() +static gboolean send_message(DBusGConnection *con) +{ + DBusMessage *message; + /* Create a new signal "Crash" on the "com.redhat.CrashCatcher" interface, + * from the object "/com/redhat/CrashCatcher". */ + message = dbus_message_new_signal("/com/redhat/CrashCatcher/Crash", + "com.redhat.CrashCatcher", "Crash"); + if(!message){ + fprintf(stderr,"Message creating error"); + } + char *progname = "Foo"; + /* Append some info to the signal */ + dbus_message_append_args(message,DBUS_TYPE_STRING, &progname, DBUS_TYPE_INVALID); + /* get the DBusConnection */ + DBusConnection *dbus_con = dbus_g_connection_get_connection(con); + /* Send the signal via low level dbus function coz glib doesn't seem to work */ + if(!dbus_connection_send(dbus_con, message, NULL)){ + printf("Error while sending message\n"); + } + printf("flushing bus %p\n", dbus_con); + dbus_connection_flush(dbus_con); + /* Free the signal */ + dbus_message_unref(message); + /* Tell the user we send a signal */ + g_print("Message sent!\n"); + /* Return TRUE to tell the event loop we want to be called again */ + return TRUE; +} + + +CDBusManager::CDBusManager() +{ + GError *error = NULL; + g_type_init(); + /* first we need to connect to dbus */ + m_nBus = dbus_g_bus_get(DBUS_BUS, &error); + if(!m_nBus) + throw std::string("Couldn't connect to dbus") + error->message; +} + +CDBusManager::~CDBusManager() +{ +} + +/* register name com.redhat.CrashCatcher on dbus */ +void CDBusManager::RegisterService() +{ + GError *error = NULL; + guint request_name_result; + g_type_init(); + // then we need a proxy to talk to dbus + m_nBus_proxy = dbus_g_proxy_new_for_name(m_nBus, DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + if(!m_nBus_proxy){ + std::cerr << "Error while creating dbus proxy!" << error->message << std::endl; + } + /* and register our name */ + if (!dbus_g_proxy_call(m_nBus_proxy, "RequestName", &error, + G_TYPE_STRING, CC_DBUS_NAME, + G_TYPE_UINT, 0, + G_TYPE_INVALID, + G_TYPE_UINT, &request_name_result, + G_TYPE_INVALID)) + { + throw std::string("Failed to acquire com.redhat.CrashCatcher:") + error->message ; + } +#ifdef DEBUG + std::cout << "Service running" << std::endl; +#endif +} + +void CDBusManager::ConnectToDaemon() +{ + GError *error = NULL; + guint request_name_result; + g_type_init(); + /* create a proxy object to talk and listen to CC daemon */ + m_nCCBus_proxy = dbus_g_proxy_new_for_name_owner(m_nBus, CC_DBUS_NAME, + CC_DBUS_PATH_NOTIFIER, + CC_DBUS_IFACE, &error); + if(!m_nCCBus_proxy){ +#ifdef DEBUG + std::cerr << "Couldn't connect to daemon via dbus: " << error->message << std::endl; +#endif + throw std::string(error->message); + } +#ifdef DEBUG + std::cout << "Connected! Waiting for signals\n" << std::endl; +#endif +} + +void CDBusManager::RegisterToMessage(const std::string& pMessage, GCallback handler, void * data, GClosureNotify free_data_func) +{ +#ifdef DEBUG + std::cout << "Trying to register" << std::endl; +#endif /*DEBUG*/ + /* Register dbus signal marshaller */ + dbus_g_object_register_marshaller(marshal_VOID__STRING, + G_TYPE_NONE, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_add_signal(m_nCCBus_proxy,"Crash",G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(m_nCCBus_proxy,"Crash",handler,NULL, NULL); +#ifdef DEBUG + std::cout << "Register done" << std::endl; +#endif /*DEBUG*/ +} + +bool CDBusManager::GSendMessage(const std::string& pMessage, const std::string& pMessParam) +{ + DBusMessage *message; + /* Create a new signal "Crash" on the "com.redhat.CrashCatcher" interface, + * from the object "/com/redhat/CrashCatcher/Crash". */ + message = dbus_message_new_signal ("/com/redhat/CrashCatcher/Crash", + "com.redhat.CrashCatcher", pMessage.c_str()); + if(!message){ + std::cerr << "Message creating error" << std::endl; + } +#ifdef DEBUG + std::cerr << message << std::endl; +#endif + const char *progname = pMessParam.c_str(); + /* Append some info to the signal */ + dbus_message_append_args(message,DBUS_TYPE_STRING, &progname, DBUS_TYPE_INVALID); + /* Send the signal */ + dbus_g_proxy_send(m_nCCBus_proxy, message, NULL); + /* Free the signal */ + dbus_message_unref(message); +#ifdef DEBUG + g_print("Message sent!\n"); +#endif + /* Return TRUE to tell the event loop we want to be called again */ + return TRUE; +} + +bool CDBusManager::SendMessage(const std::string& pMessage, const std::string& pMessParam) +{ + DBusMessage *message; + const char *progname = pMessParam.c_str(); + /* Create a new signal "Crash" on the "com.redhat.CrashCatcher" interface, + * from the object "/com/redhat/CrashCatcher/Crash". */ + message = dbus_message_new_signal ("/com/redhat/CrashCatcher/Crash", + "com.redhat.CrashCatcher", pMessage.c_str()); + if(!message){ + std::cerr << "Message creating error" << std::endl; + } +#ifdef DEBUG + std::cerr << message << std::endl; +#endif + /* Add program name as the message argument */ + dbus_message_append_args(message,DBUS_TYPE_STRING, &progname, DBUS_TYPE_INVALID); + /* Send the signal */ + DBusConnection *dbus_con = dbus_g_connection_get_connection(m_nBus); + /* Send the signal via low level dbus functio coz glib sucks */ + if(!dbus_connection_send(dbus_con, message, NULL)){ + throw "Error while sending message"; + } + /* flush the connection, otherwise, it won't show on dbus? */ + dbus_connection_flush(dbus_con); + /* Free the signal */ + dbus_message_unref(message); +#ifdef DEBUG + g_print("Message sent!\n"); +#endif + /* Return TRUE to tell the event loop we want to be called again */ + return TRUE; +} + + +// just for testing purposes +void CDBusManager::LoopSend() +{ + g_timeout_add(1000, (GSourceFunc)send_message, m_nBus); +} + +void CDBusManager::Unregister() +{ + std::cerr << "Unregister" << std::endl; +} diff --git a/lib/DBus/DBusManager.h b/lib/DBus/DBusManager.h new file mode 100644 index 00000000..e3537f89 --- /dev/null +++ b/lib/DBus/DBusManager.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) + Copyright (C) 2009 RedHat inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + */ + +#ifndef DBUS_H_ +#define DBUS_H_ + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <dbus/dbus.h> +#include <glib.h> +#include <string> + +#define CC_DBUS_NAME "com.redhat.CrashCatcher" +#define CC_DBUS_PATH "/com/redhat/CrashCatcher" +#define CC_DBUS_IFACE "com.redhat.CrashCatcher" +#define DBUS_BUS DBUS_BUS_SYSTEM +#define CC_DBUS_PATH_NOTIFIER "/com/redhat/CrashCatcher/Crash" + +class CDBusManager +{ + private: + DBusGConnection *m_nBus; + DBusGProxy *m_nBus_proxy; + DBusGProxy *m_nCCBus_proxy; + + public: + CDBusManager(); + ~CDBusManager(); + bool SendMessage(const std::string& pMessage, const std::string& pMessParam); + bool GSendMessage(const std::string& pMessage, const std::string& pMessParam); + void RegisterService(); + void ConnectToService(); + void ConnectToDaemon(); + void LoopSend(); + void Unregister(); + void RegisterToMessage(const std::string& pMessage, GCallback handler, void * data, GClosureNotify free_data_func); +}; + +#endif /*DBUS_H_*/ diff --git a/lib/DBus/Makefile.am b/lib/DBus/Makefile.am new file mode 100644 index 00000000..0d4d9f6e --- /dev/null +++ b/lib/DBus/Makefile.am @@ -0,0 +1,11 @@ +lib_LTLIBRARIES = libDBus.la +libDBus_la_SOURCES = DBusManager.cpp DBusManager.h marshal.c marshal.h +libDBus_la_LDFLAGS = -version-info 0:1:0 +libDBus_la_LIBADD = $(DBUS_GLIB_LIBS) +libDBus_la_CPPFLAGS = $(DBUS_GLIB_CFLAGS) + + +check_PROGRAMS = test +test_SOURCES = test.cpp +test_LDADD = libDBus.la $(DL_LIBS) +test_CPPFLAGS = $(DBUS_GLIB_CFLAGS) diff --git a/lib/DBus/marshal.c b/lib/DBus/marshal.c new file mode 100644 index 00000000..247bf1bb --- /dev/null +++ b/lib/DBus/marshal.c @@ -0,0 +1,51 @@ + +#include <glib-object.h> + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* VOID:STRING (marshal.list:1) */ + diff --git a/lib/DBus/marshal.h b/lib/DBus/marshal.h new file mode 100644 index 00000000..60608245 --- /dev/null +++ b/lib/DBus/marshal.h @@ -0,0 +1,15 @@ + +#ifndef __marshal_MARSHAL_H__ +#define __marshal_MARSHAL_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* VOID:STRING (marshal.list:1) */ +#define marshal_VOID__STRING g_cclosure_marshal_VOID__STRING + +G_END_DECLS + +#endif /* __marshal_MARSHAL_H__ */ + diff --git a/lib/DBus/marshal.list b/lib/DBus/marshal.list new file mode 100644 index 00000000..30ba5d8d --- /dev/null +++ b/lib/DBus/marshal.list @@ -0,0 +1 @@ +VOID:STRING diff --git a/lib/DBus/test.cpp b/lib/DBus/test.cpp new file mode 100644 index 00000000..8f1d66cf --- /dev/null +++ b/lib/DBus/test.cpp @@ -0,0 +1,76 @@ +/* + Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com) + Copyright (C) 2009 RedHat inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + */ + +#include "DBusManager.h" +#include <cstring> +#include <iostream> +#include <climits> +#include <stdlib.h> + +static void +print_cb(DBusGProxy *proxy, char* progname, gpointer user_data) +{ + DBusError error; + dbus_error_init (&error); + std::cerr << "Application " << progname << " has crashed!" << std::endl; +} + +int main(int argc, char** argv){ + GMainLoop *mainloop; + mainloop = g_main_loop_new(NULL, FALSE); + + //no sanity check, it's just a testing program! + if (argc < 2){ + std::cout << "Usage: " << argv[0] << " {s|c}" << std::endl; + return 0; + } + //service + if (strcmp(argv[1], "s") == 0){ + std::cout << "Service: " << std::endl; + CDBusManager dm; + try + { + dm.RegisterService(); + } + catch(std::string err) + { + std::cerr << err << std::endl; + return -1; + } + dm.LoopSend(); + + g_main_loop_run(mainloop); + } + //client + else if (strcmp(argv[1], "c") == 0){ + CDBusManager dm; + try + { + dm.ConnectToService(); + } + catch(std::string error) + { + std::cerr << error << std::endl; + return -1; + } + dm.RegisterToMessage("Crash",G_CALLBACK(print_cb),NULL,NULL); + g_main_loop_run(mainloop); + } + return 0; +} |