GDBus: API and usage cleanup

DBusCallObject and friends were not used anywhere. Removed.

DBusObject and DBusRemoteObject used pure virtual methods to let
derived classes provide information about interface, path,
destination, method and the connection. The idea behind that was that
most of these strings are static and thus do not need to be copied.

The downside is that one had to derive from these classes in order to
provide the required information. The same class could not own two
instances of the generic DBusObject to access two different
destinations. It also sprinkled the code for setting up D-Bus
operations into several different places (constructor, class definition).

Now the information is passed to the DBus[Remote]Object constructor
and stored in the classes, which are thus merely containers for the
information and thus easier to use. Users of the classes still derive
from them, to keep the change smaller, although that is no longer
necessary.

Removed plain DBusConnection pointers from the C++ interface, return
DBusConnectionPtr instead. The exception is DBusObject, which still
returns plain pointers owned by the instance (as before) to ease
integration with the underlying D-Bus library. DBUS_CONNECTION_TYPE
is not needed.

This revealed that quite some code incorrectly took another reference
to the connection when assigning to DBusConnectionPtr (assignment
always increases the refcount, only in the constructor is that
optional). As a result the private connections were never
destructed. Apparently there were some global pointers to active
connections, so that this (minor) resource leak didn't show up in
valgrind.

It also showed that the closing of the D-Bus connection never happened
properly, although libdbus requires it. The ref counting mechanism
cannot be used for this because it cannot be checked whether the last
reference is about to be dropped. The slightly hackish solution is to
designate one DBusObject as the "main owner" of the connection. When
that object destructs, it closes the connection. There might still be
some other references; they simply cannot (and shouldn't) send or
receive messages anymore.
This commit is contained in:
Patrick Ohly 2011-12-16 13:17:08 +01:00
parent 996a237b18
commit b34591dd62
16 changed files with 228 additions and 271 deletions

View File

@ -34,14 +34,18 @@ using namespace GDBusCXX;
SE_BEGIN_CXX
BluezManager::BluezManager(Server &server) :
DBusRemoteObject(!strcmp(getEnv("DBUS_TEST_BLUETOOTH", ""), "none") ?
NULL : /* simulate missing Bluez */
GDBusCXX::dbus_get_bus_connection(!strcmp(getEnv("DBUS_TEST_BLUETOOTH", ""), "session") ?
"SESSION" : /* use our own Bluez stub */
"SYSTEM" /* use real Bluez */,
NULL, true, NULL),
"/", "org.bluez.Manager", "org.bluez",
true),
m_server(server),
m_adapterChanged(*this, "DefaultAdapterChanged")
{
const char *bluetoothTest = getenv ("DBUS_TEST_BLUETOOTH");
m_bluezConn = (bluetoothTest && !strcmp(bluetoothTest, "none")) ? NULL :
dbus_get_bus_connection((bluetoothTest && !strcmp(bluetoothTest, "session")) ?
"SESSION" : "SYSTEM", NULL, true, NULL);
if(m_bluezConn) {
if (getConnection()) {
m_done = false;
DBusClientCall1<DBusObject_t> getAdapter(*this, "DefaultAdapter");
getAdapter(boost::bind(&BluezManager::defaultAdapterCb, this, _1, _2 ));
@ -74,9 +78,11 @@ void BluezManager::defaultAdapterCb(const DBusObject_t &adapter, const string &e
m_adapter.reset(new BluezAdapter(*this, adapter));
}
BluezManager::BluezAdapter::BluezAdapter(BluezManager &manager, const string &path)
: m_manager(manager), m_path(path), m_devNo(0), m_devReplies(0),
m_deviceRemoved(*this, "DeviceRemoved"), m_deviceAdded(*this, "DeviceCreated")
BluezManager::BluezAdapter::BluezAdapter(BluezManager &manager, const string &path) :
DBusRemoteObject(manager.getConnection(),
path, "org.bluez.Adapter", "org.bluez"),
m_manager(manager), m_devNo(0), m_devReplies(0),
m_deviceRemoved(*this, "DeviceRemoved"), m_deviceAdded(*this, "DeviceCreated")
{
DBusClientCall1<std::vector<DBusObject_t> > listDevices(*this, "ListDevices");
listDevices(boost::bind(&BluezAdapter::listDevicesCb, this, _1, _2));
@ -124,8 +130,10 @@ void BluezManager::BluezAdapter::deviceCreated(const DBusObject_t &object)
m_devices.push_back(bluezDevice);
}
BluezManager::BluezDevice::BluezDevice (BluezAdapter &adapter, const string &path)
: m_adapter(adapter), m_path(path), m_reply(false), m_propertyChanged(*this, "PropertyChanged")
BluezManager::BluezDevice::BluezDevice (BluezAdapter &adapter, const string &path) :
GDBusCXX::DBusRemoteObject(adapter.m_manager.getConnection(),
path, "org.bluez.Device", "org.bluez"),
m_adapter(adapter), m_reply(false), m_propertyChanged(*this, "PropertyChanged")
{
DBusClientCall1<PropDict> getProperties(*this, "GetProperties");
getProperties(boost::bind(&BluezDevice::getPropertiesCb, this, _1, _2));

View File

@ -54,11 +54,6 @@ class GLibNotify;
class BluezManager : public GDBusCXX::DBusRemoteObject {
public:
BluezManager(Server &server);
virtual const char *getDestination() const {return "org.bluez";}
virtual const char *getPath() const {return "/";}
virtual const char *getInterface() const {return "org.bluez.Manager";}
virtual DBUS_CONNECTION_TYPE *getConnection() const {return m_bluezConn.get();}
bool isDone() { return m_done; }
private:
@ -74,10 +69,6 @@ private:
public:
BluezAdapter (BluezManager &manager, const std::string &path);
virtual const char *getDestination() const {return "org.bluez";}
virtual const char *getPath() const {return m_path.c_str();}
virtual const char *getInterface() const {return "org.bluez.Adapter";}
virtual DBUS_CONNECTION_TYPE *getConnection() const {return m_manager.getConnection();}
void checkDone(bool forceDone = false)
{
if(forceDone || m_devReplies >= m_devNo) {
@ -101,8 +92,6 @@ private:
void deviceCreated(const GDBusCXX::DBusObject_t &object);
BluezManager &m_manager;
/** the object path of adapter */
std::string m_path;
/** the number of device for the default adapter */
int m_devNo;
/** the number of devices having reply */
@ -132,10 +121,6 @@ private:
BluezDevice (BluezAdapter &adapter, const std::string &path);
virtual const char *getDestination() const {return "org.bluez";}
virtual const char *getPath() const {return m_path.c_str();}
virtual const char *getInterface() const {return "org.bluez.Device";}
virtual DBUS_CONNECTION_TYPE *getConnection() const {return m_adapter.m_manager.getConnection();}
std::string getMac() { return m_mac; }
/**
@ -155,8 +140,6 @@ private:
void propertyChanged(const std::string &name, const boost::variant<std::vector<std::string>, std::string> &prop);
BluezAdapter &m_adapter;
/** the object path of the device */
std::string m_path;
/** name of the device */
std::string m_name;
/** mac address of the device */

View File

@ -396,7 +396,7 @@ Connection::Connection(Server &server,
const std::string &sessionID,
const StringMap &peer,
bool must_authenticate) :
DBusObjectHelper(conn.get(),
DBusObjectHelper(conn,
std::string("/org/syncevolution/Connection/") + sessionID,
"org.syncevolution.Connection",
boost::bind(&Server::autoTermCallback, &server)),

View File

@ -23,12 +23,17 @@
SE_BEGIN_CXX
ConnmanClient::ConnmanClient(Server &server):
DBusRemoteObject(!strcmp(getEnv("DBUS_TEST_CONNMAN", ""), "none") ?
NULL : /* simulate missing ConnMan */
GDBusCXX::dbus_get_bus_connection(!strcmp(getEnv("DBUS_TEST_CONNMAN", ""), "session") ?
"SESSION" : /* use our own ConnMan stub */
"SYSTEM" /* use real ConnMan */,
NULL, true, NULL),
"/", "net.connman.Manager", "net.connman", true),
m_server(server),
m_propertyChanged(*this, "PropertyChanged")
{
const char *connmanTest = getenv ("DBUS_TEST_CONNMAN");
m_connmanConn = GDBusCXX::dbus_get_bus_connection(connmanTest ? "SESSION": "SYSTEM", NULL, true, NULL);
if (m_connmanConn){
if (getConnection()) {
typedef std::map <std::string, boost::variant <std::vector <std::string> > > PropDict;
GDBusCXX::DBusClientCall1<PropDict> getProp(*this,"GetProperties");
getProp (boost::bind(&ConnmanClient::getPropCb, this, _1, _2));

View File

@ -38,10 +38,6 @@ class ConnmanClient : public GDBusCXX::DBusRemoteObject
{
public:
ConnmanClient (Server &server);
virtual const char *getDestination() const {return "net.connman";}
virtual const char *getPath() const {return "/";}
virtual const char *getInterface() const {return "net.connman.Manager";}
virtual DBUS_CONNECTION_TYPE *getConnection() const {return m_connmanConn.get();}
void propertyChanged(const std::string &name,
const boost::variant<std::vector<std::string>, std::string> &prop);
@ -49,11 +45,10 @@ public:
void getPropCb(const std::map <std::string, boost::variant <std::vector <std::string> > >& props, const std::string &error);
/** TRUE if watching ConnMan status */
bool isAvailable() { return m_connmanConn; }
bool isAvailable() { return getConnection() != NULL; }
private:
Server &m_server;
GDBusCXX::DBusConnectionPtr m_connmanConn;
GDBusCXX::SignalWatch2 <std::string, boost::variant<std::vector<std::string>, std::string> > m_propertyChanged;
};

View File

@ -109,6 +109,8 @@ int main(int argc, char **argv, char **envp)
if (!conn) {
err.throwFailure("dbus_get_bus_connection()", " failed - server already running?");
}
// make this object the main owner of the connection
DBusObject obj(conn, "foo", "bar", true);
SyncEvo::Server server(loop, shutdownRequested, restart, conn, duration);
server.activate();

View File

@ -24,12 +24,16 @@
SE_BEGIN_CXX
NetworkManagerClient::NetworkManagerClient(Server &server) :
DBusRemoteObject(GDBusCXX::dbus_get_bus_connection("SYSTEM", NULL, true, NULL),
"/org/freedesktop/NetworkManager",
"org.freedesktop.NetworkManager",
"org.freedesktop.NetworkManager",
true),
m_server(server),
m_stateChanged(*this, "StateChanged"),
m_properties(*this)
{
m_networkManagerConn = GDBusCXX::dbus_get_bus_connection("SYSTEM", NULL, true, NULL);
if(m_networkManagerConn) {
if (getConnection()) {
m_properties.get();
m_stateChanged.activate(boost::bind(
&NetworkManagerClient::stateChanged,
@ -64,9 +68,12 @@ void NetworkManagerClient::stateChanged(uint32_t uiState)
NetworkManagerClient::NetworkManagerProperties::NetworkManagerProperties(
NetworkManagerClient& manager) :
GDBusCXX::DBusRemoteObject(manager.getConnection(),
"/org/freedesktop/NetworkManager",
"org.freedesktop.DBus.Properties",
"org.freedesktop.NetworkManager"),
m_manager(manager)
{
}
void NetworkManagerClient::NetworkManagerProperties::get()

View File

@ -60,23 +60,10 @@ public:
public:
NetworkManagerClient(Server& server);
virtual const char *getDestination() const {
return "org.freedesktop.NetworkManager";
}
virtual const char *getPath() const {
return "/org/freedesktop/NetworkManager";
}
virtual const char *getInterface() const {
return "org.freedesktop.NetworkManager";
}
virtual DBUS_CONNECTION_TYPE *getConnection() const {
return m_networkManagerConn.get();
}
void stateChanged(uint32_t uiState);
/** TRUE if watching Network Manager status */
bool isAvailable() { return m_networkManagerConn; }
bool isAvailable() { return getConnection() != NULL; }
private:
@ -85,18 +72,6 @@ private:
public:
NetworkManagerProperties(NetworkManagerClient& manager);
virtual const char *getDestination() const {
return "org.freedesktop.NetworkManager";
}
virtual const char *getPath() const {
return "/org/freedesktop/NetworkManager";
}
virtual const char *getInterface() const {
return "org.freedesktop.DBus.Properties";
}
virtual DBUS_CONNECTION_TYPE* getConnection() const {
return m_manager.getConnection();
}
void get();
void getCallback(const boost::variant<uint32_t, std::string> &prop,
const std::string &error);
@ -105,7 +80,6 @@ private:
};
Server &m_server;
GDBusCXX::DBusConnectionPtr m_networkManagerConn;
GDBusCXX::SignalWatch1<uint32_t> m_stateChanged;
NetworkManagerProperties m_properties;
};

View File

@ -214,7 +214,7 @@ Server::Server(GMainLoop *loop,
boost::shared_ptr<Restart> &restart,
const DBusConnectionPtr &conn,
int duration) :
DBusObjectHelper(conn.get(),
DBusObjectHelper(conn,
"/org/syncevolution/Server",
"org.syncevolution.Server",
boost::bind(&Server::autoTermCallback, this)),

View File

@ -29,13 +29,14 @@ void intrusive_ptr_release(DBusPendingCall *call) { dbus_pending_call_unref (cal
namespace GDBusCXX {
DBusConnection *dbus_get_bus_connection(const char *busType,
const char *interface,
bool unshared,
DBusErrorCXX *err)
DBusConnectionPtr dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
DBusErrorCXX *err)
{
return b_dbus_setup_bus(boost::iequals(busType, "SYSTEM") ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
interface, unshared, err);;
return DBusConnectionPtr(b_dbus_setup_bus(boost::iequals(busType, "SYSTEM") ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
name, unshared, err),
false);
}
}

View File

@ -84,7 +84,6 @@ void intrusive_ptr_release(DBusPendingCall *call);
* keep changes to a minimum while supporting both dbus
* implementations, this is made to be a define. The intention is to
* remove the define once the in-tree gdbus is dropped. */
#define DBUS_CONNECTION_TYPE DBusConnection
#define DBUS_MESSAGE_TYPE DBusMessage
#define DBUS_NEW_ERROR_MSG b_dbus_create_error
@ -165,10 +164,10 @@ class DBusErrorCXX : public DBusError
}
};
DBusConnection *dbus_get_bus_connection(const char *busType,
const char *interface,
bool unshared,
DBusErrorCXX *err);
DBusConnectionPtr dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
DBusErrorCXX *err);
/**
* Special type for object paths. A string in practice.
@ -334,16 +333,65 @@ template<class A> struct Get <A &>
};
/**
* interface expected by EmitSignal
* combines D-Bus connection, path and interface
*/
class DBusObject
{
public:
virtual ~DBusObject() {}
DBusConnectionPtr m_conn;
std::string m_path;
std::string m_interface;
bool m_closeConnection;
virtual DBusConnection *getConnection() const = 0;
virtual const char *getPath() const = 0;
virtual const char *getInterface() const = 0;
public:
/**
* @param closeConnection set to true if the connection
* is private and this instance of
* DBusObject is meant to be the
* last user of the connection;
* when this DBusObject deconstructs,
* it'll close the connection
* (required by libdbus for private
* connections; the mechanism in GDBus for
* this didn't work)
*/
DBusObject(const DBusConnectionPtr &conn,
const std::string &path,
const std::string &interface,
bool closeConnection = false) :
m_conn(conn),
m_path(path),
m_interface(interface),
m_closeConnection(closeConnection)
{}
~DBusObject() {
if (m_closeConnection &&
m_conn) {
dbus_connection_close(m_conn.get());
}
}
DBusConnection *getConnection() const { return m_conn.get(); }
const char *getPath() const { return m_path.c_str(); }
const char *getInterface() const { return m_interface.c_str(); }
};
/**
* adds destination to D-Bus connection, path and interface
*/
class DBusRemoteObject : public DBusObject
{
std::string m_destination;
public:
DBusRemoteObject(const DBusConnectionPtr &conn,
const std::string &path,
const std::string &interface,
const std::string &destination,
bool closeConnection = false) :
DBusObject(conn, path, interface, closeConnection),
m_destination(destination)
{}
const char *getDestination() const { return m_destination.c_str(); }
};
class EmitSignal0
@ -703,22 +751,17 @@ template <class T> class DBusVector {
*/
class DBusObjectHelper : public DBusObject
{
DBusConnectionPtr m_conn;
std::string m_path;
std::string m_interface;
boost::function<void (void)> m_callback;
bool m_activated;
DBusVector<BDBusMethodTable> m_methods;
DBusVector<BDBusSignalTable> m_signals;
public:
DBusObjectHelper(DBusConnection *conn,
DBusObjectHelper(const DBusConnectionPtr &conn,
const std::string &path,
const std::string &interface,
const boost::function<void (void)> &callback = boost::function<void (void)>()) :
m_conn(conn),
m_path(path),
m_interface(interface),
DBusObject(conn, path, interface),
m_callback(callback),
m_activated(false)
{
@ -729,10 +772,6 @@ class DBusObjectHelper : public DBusObject
deactivate();
}
virtual DBusConnection *getConnection() const { return m_conn.get(); }
virtual const char *getPath() const { return m_path.c_str(); }
virtual const char *getInterface() const { return m_interface.c_str(); }
/**
* binds a member to the this pointer of its instance
* and invokes it when the specified method is called
@ -3734,26 +3773,6 @@ struct MakeMethodEntry< boost::function<void ()> >
}
};
/**
* interface to refer to a remote object
*/
class DBusRemoteObject : public DBusObject
{
public:
virtual const char *getDestination() const = 0;
virtual ~DBusRemoteObject() {}
};
/**
* interface expected by DBusClient
*/
class DBusCallObject : public DBusRemoteObject
{
public:
/* The method name for the calling dbus method */
virtual const char *getMethod() const =0;
virtual ~DBusCallObject() {}
};
template <class T>
class DBusClientCall
{
@ -3789,16 +3808,6 @@ public:
{}
};
DBusClientCall(const DBusCallObject &object, DBusCallback dbusCallback)
:m_destination (object.getDestination()),
m_path (object.getPath()),
m_interface (object.getInterface()),
m_method (object.getMethod()),
m_conn (object.getConnection()),
m_dbusCallback(dbusCallback)
{
}
DBusClientCall(const DBusRemoteObject &object, const std::string &method, DBusCallback dbusCallback)
:m_destination (object.getDestination()),
m_path (object.getPath()),
@ -3944,11 +3953,6 @@ class DBusClientCall0 : public DBusClientCall<boost::function<void (const std::s
}
public:
DBusClientCall0 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall0::dbusCallback)
{
}
DBusClientCall0 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall0::dbusCallback)
{
@ -3984,11 +3988,6 @@ class DBusClientCall1 : public DBusClientCall<boost::function<void (const R1 &,
}
public:
DBusClientCall1 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall1::dbusCallback)
{
}
DBusClientCall1 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall1::dbusCallback)
{
@ -4026,11 +4025,6 @@ class DBusClientCall2 : public DBusClientCall<boost::function<
}
public:
DBusClientCall2 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall2::dbusCallback)
{
}
DBusClientCall2 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall2::dbusCallback)
{
@ -4069,11 +4063,6 @@ class DBusClientCall3 : public DBusClientCall<boost::function<
}
public:
DBusClientCall3 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall3::dbusCallback)
{
}
DBusClientCall3 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall3::dbusCallback)
{

View File

@ -176,7 +176,7 @@ class DBusTest : public Test, private Test2
DBusObjectHelper m_secondary;
public:
DBusTest(DBusConnection *conn) :
DBusTest(const DBusConnectionPtr conn) :
m_object(conn, "/test", "org.example.Test"),
// same path!
m_secondary(conn, m_object.getPath(), "org.example.Secondary"),
@ -244,7 +244,7 @@ using namespace GDBusCXX;
int main(int argc, char *argv[])
{
DBusConnection *conn;
DBusConnectionPtr conn;
DBusErrorCXX err;
struct sigaction sa;
@ -260,7 +260,7 @@ int main(int argc, char *argv[])
main_loop = g_main_loop_new(NULL, FALSE);
conn = dbus_get_bus_connection("SESSION", "org.example", false, &err);
if (conn == NULL) {
if (!conn) {
if (dbus_error_is_set(&err) == TRUE) {
fprintf(stderr, "%s\n", err.message);
dbus_error_free(&err);

View File

@ -29,12 +29,12 @@ namespace GDBusCXX {
MethodHandler::MethodMap MethodHandler::m_methodMap;
boost::function<void (void)> MethodHandler::m_callback;
GDBusConnection *dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
DBusErrorCXX *err)
DBusConnectionPtr dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
DBusErrorCXX *err)
{
GDBusConnection *conn;
DBusConnectionPtr conn;
GError* error = NULL;
if(unshared) {
@ -48,11 +48,12 @@ GDBusConnection *dbus_get_bus_connection(const char *busType,
return NULL;
}
// Here we set up a private client connection using the chosen bus' address.
conn = g_dbus_connection_new_for_address_sync(address,
(GDBusConnectionFlags)
(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
NULL, NULL, &error);
conn = DBusConnectionPtr(g_dbus_connection_new_for_address_sync(address,
(GDBusConnectionFlags)
(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
NULL, NULL, &error),
false);
g_free(address);
if(conn == NULL) {
@ -63,8 +64,11 @@ GDBusConnection *dbus_get_bus_connection(const char *busType,
}
} else {
// This returns a singleton, shared connection object.
conn = g_bus_get_sync(boost::iequals(busType, "SESSION") ? G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM,
NULL, &error);
conn = DBusConnectionPtr(g_bus_get_sync(boost::iequals(busType, "SESSION") ?
G_BUS_TYPE_SESSION :
G_BUS_TYPE_SYSTEM,
NULL, &error),
false);
if(conn == NULL) {
if (err) {
err->set(error);
@ -74,9 +78,9 @@ GDBusConnection *dbus_get_bus_connection(const char *busType,
}
if(name) {
g_bus_own_name_on_connection(conn, name, G_BUS_NAME_OWNER_FLAGS_NONE,
g_bus_own_name_on_connection(conn.get(), name, G_BUS_NAME_OWNER_FLAGS_NONE,
NULL, NULL, NULL, NULL);
g_dbus_connection_set_exit_on_close(conn, TRUE);
g_dbus_connection_set_exit_on_close(conn.get(), TRUE);
}
return conn;

View File

@ -70,11 +70,13 @@
#include <boost/variant/get.hpp>
#include <boost/algorithm/string/predicate.hpp>
/* The connection and message are the only client-exposed types from
* the C API. To keep changes to a minimum while supporting both dbus
/* The SyncEvolution exception handler must integrate into the D-Bus
* C++ wrapper. In contrast to the rest of the code, that handler uses
* some of the internal classes.
*
* To keep changes to a minimum while supporting both dbus
* implementations, this is made to be a define. The intention is to
* remove the define once the in-tree gdbus is dropped. */
#define DBUS_CONNECTION_TYPE GDBusConnection
#define DBUS_MESSAGE_TYPE GDBusMessage
#define DBUS_NEW_ERROR_MSG g_dbus_message_new_method_error
@ -177,10 +179,10 @@ class DBusErrorCXX
std::string getMessage() const { return m_error ? m_error->message : ""; }
};
GDBusConnection *dbus_get_bus_connection(const char *busType,
const char*interface,
bool unshared,
DBusErrorCXX *err);
DBusConnectionPtr dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
DBusErrorCXX *err);
/**
* Special type for object paths. A string in practice.
@ -363,16 +365,66 @@ template<class A> struct Get <A &>
};
/**
* interface expected by EmitSignal
* combines D-Bus connection, path and interface
*/
class DBusObject
{
public:
virtual ~DBusObject() {}
DBusConnectionPtr m_conn;
std::string m_path;
std::string m_interface;
bool m_closeConnection;
virtual GDBusConnection *getConnection() const = 0;
virtual const char *getPath() const = 0;
virtual const char *getInterface() const = 0;
public:
/**
* @param closeConnection set to true if the connection
* is private and this instance of
* DBusObject is meant to be the
* last user of the connection;
* when this DBusObject deconstructs,
* it'll close the connection
* (required by libdbus for private
* connections; the mechanism in GDBus for
* this didn't work)
*/
DBusObject(const DBusConnectionPtr &conn,
const std::string &path,
const std::string &interface,
bool closeConnection = false) :
m_conn(conn),
m_path(path),
m_interface(interface),
m_closeConnection(closeConnection)
{}
~DBusObject() {
if (m_closeConnection &&
m_conn) {
// TODO: is this also necessary for GIO GDBus?
// dbus_connection_close(m_conn.get());
}
}
GDBusConnection *getConnection() const { return m_conn.get(); }
const char *getPath() const { return m_path.c_str(); }
const char *getInterface() const { return m_interface.c_str(); }
};
/**
* adds destination to D-Bus connection, path and interface
*/
class DBusRemoteObject : public DBusObject
{
std::string m_destination;
public:
DBusRemoteObject(const DBusConnectionPtr &conn,
const std::string &path,
const std::string &interface,
const std::string &destination,
bool closeConnection = false) :
DBusObject(conn, path, interface, closeConnection),
m_destination(destination)
{}
const char *getDestination() const { return m_destination.c_str(); }
};
class EmitSignal0
@ -821,22 +873,17 @@ struct MakeMethodEntry
*/
class DBusObjectHelper : public DBusObject
{
DBusConnectionPtr m_conn;
guint m_connId;
std::string m_path;
std::string m_interface;
bool m_activated;
GPtrArray *m_methods;
GPtrArray *m_signals;
public:
DBusObjectHelper(GDBusConnection *conn,
DBusObjectHelper(DBusConnectionPtr conn,
const std::string &path,
const std::string &interface,
const boost::function<void (void)> &callback = boost::function<void (void)>()) :
m_conn(conn),
m_path(path),
m_interface(interface),
DBusObject(conn, path, interface),
m_activated(false),
m_methods(g_ptr_array_new_with_free_func((GDestroyNotify)g_dbus_method_info_unref)),
m_signals(g_ptr_array_new_with_free_func((GDestroyNotify)g_dbus_signal_info_unref))
@ -854,7 +901,7 @@ class DBusObjectHelper : public DBusObject
MethodHandler::MethodMap::iterator iter_end(MethodHandler::m_methodMap.end());
MethodHandler::MethodMap::iterator first_to_erase(iter_end);
MethodHandler::MethodMap::iterator last_to_erase(iter_end);
const std::string prefix(MethodHandler::make_prefix(m_path.c_str()));
const std::string prefix(MethodHandler::make_prefix(getPath()));
while (iter != iter_end) {
const bool prefix_equal(!iter->first.compare(0, prefix.size(), prefix));
@ -880,10 +927,6 @@ class DBusObjectHelper : public DBusObject
}
}
virtual GDBusConnection *getConnection() const { return m_conn.get(); }
virtual const char *getPath() const { return m_path.c_str(); }
virtual const char *getInterface() const { return m_interface.c_str(); }
/**
* binds a member to the this pointer of its instance
* and invokes it when the specified method is called
@ -900,7 +943,7 @@ class DBusObjectHelper : public DBusObject
boost::function<M> *func = new boost::function<M>(entry_type::boostptr(method, instance));
MethodHandler::FuncWrapper wrapper(new FunctionWrapper<M>(func));
MethodHandler::CallbackPair methodAndData = std::make_pair(entry_type::methodFunction, wrapper);
const std::string key(MethodHandler::make_method_key(m_path.c_str(), name));
const std::string key(MethodHandler::make_method_key(getPath(), name));
MethodHandler::m_methodMap.insert(std::make_pair(key, methodAndData));
}
@ -922,7 +965,7 @@ class DBusObjectHelper : public DBusObject
MethodHandler::FuncWrapper wrapper(new FunctionWrapper<M>(func));
MethodHandler::CallbackPair methodAndData = std::make_pair(entry_type::methodFunction,
wrapper);
const std::string key(MethodHandler::make_method_key(m_path.c_str(), name));
const std::string key(MethodHandler::make_method_key(getPath(), name));
MethodHandler::m_methodMap.insert(std::make_pair(key, methodAndData));
}
@ -945,7 +988,7 @@ class DBusObjectHelper : public DBusObject
const boost::function<void (void)> &callback)
{
GDBusInterfaceInfo *ifInfo = g_new0(GDBusInterfaceInfo, 1);
ifInfo->name = g_strdup(m_interface.c_str());
ifInfo->name = g_strdup(getInterface());
ifInfo->methods = methods;
ifInfo->signals = signals;
ifInfo->properties = properties;
@ -980,7 +1023,7 @@ class DBusObjectHelper : public DBusObject
g_ptr_array_add(m_signals, NULL);
}
GDBusInterfaceInfo *ifInfo = g_new0(GDBusInterfaceInfo, 1);
ifInfo->name = g_strdup(m_interface.c_str());
ifInfo->name = g_strdup(getInterface());
ifInfo->methods = (GDBusMethodInfo **)g_ptr_array_free(m_methods, FALSE);
ifInfo->signals = (GDBusSignalInfo **)g_ptr_array_free(m_signals, FALSE);
m_signals = NULL;
@ -3746,26 +3789,6 @@ struct MakeMethodEntry< boost::function<void ()> >
}
};
/**
* interface to refer to a remote object
*/
class DBusRemoteObject : public DBusObject
{
public:
virtual const char *getDestination() const = 0;
virtual ~DBusRemoteObject() {}
};
/**
* interface expected by DBusClient
*/
class DBusCallObject : public DBusRemoteObject
{
public:
/* The method name for the calling dbus method */
virtual const char *getMethod() const =0;
virtual ~DBusCallObject() {}
};
template <class T>
class DBusClientCall
{
@ -3801,16 +3824,6 @@ public:
{}
};
DBusClientCall(const DBusCallObject &object, DBusCallback dbusCallback)
:m_destination (object.getDestination()),
m_path (object.getPath()),
m_interface (object.getInterface()),
m_method (object.getMethod()),
m_conn (object.getConnection()),
m_dbusCallback(dbusCallback)
{
}
DBusClientCall(const DBusRemoteObject &object, const std::string &method, DBusCallback dbusCallback)
:m_destination (object.getDestination()),
m_path (object.getPath()),
@ -3926,11 +3939,6 @@ class DBusClientCall0 : public DBusClientCall<boost::function<void (const std::s
}
public:
DBusClientCall0 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall0::dbusCallback)
{
}
DBusClientCall0 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall0::dbusCallback)
{
@ -3969,11 +3977,6 @@ class DBusClientCall1 : public DBusClientCall<boost::function<void (const R1 &,
}
public:
DBusClientCall1 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall1::dbusCallback)
{
}
DBusClientCall1 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall1::dbusCallback)
{
@ -4013,11 +4016,6 @@ class DBusClientCall2 : public DBusClientCall<boost::function<
}
public:
DBusClientCall2 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall2::dbusCallback)
{
}
DBusClientCall2 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall2::dbusCallback)
{
@ -4058,11 +4056,6 @@ class DBusClientCall3 : public DBusClientCall<boost::function<
}
public:
DBusClientCall3 (const DBusCallObject &object)
: DBusClientCall<Callback_t>(object, &DBusClientCall3::dbusCallback)
{
}
DBusClientCall3 (const DBusRemoteObject &object, const std::string &method)
: DBusClientCall<Callback_t>(object, method, &DBusClientCall3::dbusCallback)
{

View File

@ -176,7 +176,7 @@ class DBusTest : public Test, private Test2
DBusObjectHelper m_secondary;
public:
DBusTest(GDBusConnection *conn) :
DBusTest(const DBusConnectionPtr &conn) :
m_object(conn, "/test", "org.example.Test"),
// same path!
m_secondary(conn, m_object.getPath(), "org.example.Secondary"),
@ -244,7 +244,7 @@ using namespace GDBusCXX;
int main(int argc, char *argv[])
{
GDBusConnection *conn;
DBusConnectionPtr conn;
DBusErrorCXX err;
struct sigaction sa;
@ -280,10 +280,11 @@ int main(int argc, char *argv[])
test.reset();
if(!g_dbus_connection_close_sync(conn, NULL, NULL)) {
fprintf(stderr, "Problem closing connection.\n");
}
// is this really necessary?
// if(!g_dbus_connection_close_sync(conn, NULL, NULL)) {
// fprintf(stderr, "Problem closing connection.\n");
// }
g_main_loop_unref(main_loop);
return 0;

View File

@ -122,10 +122,6 @@ class RemoteDBusServer : public DBusRemoteObject
public:
RemoteDBusServer();
virtual const char *getDestination() const {return "org.syncevolution";}
virtual const char *getPath() const {return "/org/syncevolution/Server";}
virtual const char *getInterface() const {return "org.syncevolution.Server";}
virtual DBUS_CONNECTION_TYPE *getConnection() const {return m_conn.get();}
GMainLoop *getLoop() { return m_loop; }
/**
@ -238,8 +234,6 @@ private:
// the main loop
GMainLoop *m_loop;
// connection
DBusConnectionPtr m_conn;
// whether client can attach to the daemon.
// It is also used to indicate whether daemon is ready to use.
bool m_attached;
@ -285,10 +279,6 @@ class RemoteSession : public DBusRemoteObject
{
public:
RemoteSession(RemoteDBusServer &server, const std::string &path);
virtual const char *getDestination() const {return "org.syncevolution";}
virtual const char *getPath() const {return m_path.c_str();}
virtual const char *getInterface() const {return "org.syncevolution.Session";}
virtual DBUS_CONNECTION_TYPE *getConnection() const {return m_server.getConnection();}
RemoteDBusServer &getServer() { return m_server; }
/**
@ -428,9 +418,6 @@ private:
/* whether to log output */
bool m_output;
/** object path */
string m_path;
/** config name of the session */
string m_configName;
@ -591,17 +578,21 @@ int main( int argc, char **argv )
#ifdef DBUS_SERVICE
/********************** RemoteDBusServer implementation **************************/
RemoteDBusServer::RemoteDBusServer()
:m_attached(false), m_result(true),
m_replyTotal(0), m_replyCounter(0),
m_sessionChanged(*this,"SessionChanged"),
m_logOutput(*this, "LogOutput"),
m_infoReq(*this, "InfoRequest")
RemoteDBusServer::RemoteDBusServer() :
DBusRemoteObject(dbus_get_bus_connection("SESSION", NULL, true, NULL),
"/org/syncevolution/Server",
"org.syncevolution.Server",
"org.syncevolution",
true),
m_attached(false), m_result(true),
m_replyTotal(0), m_replyCounter(0),
m_sessionChanged(*this,"SessionChanged"),
m_logOutput(*this, "LogOutput"),
m_infoReq(*this, "InfoRequest")
{
m_loop = g_main_loop_new (NULL, FALSE);
m_conn = dbus_get_bus_connection("SESSION", NULL, true, NULL);
if(m_conn) {
if (getConnection()) {
//check whether we can attach to the daemon
//also set up the daemon watch when attaching to server
attachSync();
@ -1033,8 +1024,12 @@ bool RemoteDBusServer::monitor(const string &peer)
/********************** RemoteSession implementation **************************/
RemoteSession::RemoteSession(RemoteDBusServer &server,
const string &path)
:m_server(server), m_output(false), m_path(path), m_runSync(false),
const string &path) :
DBusRemoteObject(server.getConnection(),
path,
"org.syncevolution.Session",
"org.syncevolution"),
m_server(server), m_output(false), m_runSync(false),
m_statusChanged(*this, "StatusChanged")
{
m_statusChanged.activate(boost::bind(&RemoteSession::statusChangedCb, this, _1, _2, _3));