syncevolution/src/gdbusxx/gdbus-cxx-bridge.cpp
Krzesimir Nowak 3acc51416c GDBus GIO: SignalWatch activation for one-to-one connections
API adapted to the one used by GDBus libdbus. Actual implementation
didn't have to be changed.
2012-02-17 15:34:15 +01:00

204 lines
7.5 KiB
C++

/*
* Copyright (C) 2011 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "gdbus-cxx-bridge.h"
#include <stdio.h>
void intrusive_ptr_add_ref(GDBusConnection *con) { g_object_ref(con); }
void intrusive_ptr_release(GDBusConnection *con) { g_object_unref(con); }
void intrusive_ptr_add_ref(GDBusMessage *msg) { g_object_ref(msg); }
void intrusive_ptr_release(GDBusMessage *msg) { g_object_unref(msg); }
static void intrusive_ptr_add_ref(GDBusServer *server) { g_object_ref(server); }
static void intrusive_ptr_release(GDBusServer *server) { g_object_unref(server); }
namespace GDBusCXX {
MethodHandler::MethodMap MethodHandler::m_methodMap;
boost::function<void (void)> MethodHandler::m_callback;
DBusConnectionPtr dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
DBusErrorCXX *err)
{
DBusConnectionPtr conn;
GError* error = NULL;
if(unshared) {
char *address = g_dbus_address_get_for_bus_sync(boost::iequals(busType, "SESSION") ?
G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM,
NULL, &error);
if(address == NULL) {
if (err) {
err->set(error);
}
return NULL;
}
// Here we set up a private client connection using the chosen bus' address.
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) {
if (err) {
err->set(error);
}
return NULL;
}
} else {
// This returns a singleton, shared connection object.
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);
}
return NULL;
}
}
if(name) {
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.get(), TRUE);
}
return conn;
}
DBusConnectionPtr dbus_get_bus_connection(const std::string &address,
DBusErrorCXX *err)
{
GError* error = NULL;
DBusConnectionPtr conn(g_dbus_connection_new_for_address_sync(address.c_str(),
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
NULL, /* GDBusAuthObserver */
NULL, /* GCancellable */
&error),
false);
if (!conn && err) {
err->set(error);
}
return conn;
}
boost::shared_ptr<DBusServerCXX> DBusServerCXX::listen(const std::string &address, DBusErrorCXX *err)
{
GDBusServer *server = NULL;
const char *realAddr = address.c_str();
char buffer[80];
gchar *guid = g_dbus_generate_guid();
GError *error = NULL;
if (address.empty()) {
realAddr = buffer;
for (int counter = 1; counter < 100 && !server; counter++) {
if (error) {
// previous attempt failed
g_debug("setting up D-Bus server on %s failed, trying next address: %s",
realAddr,
error->message);
g_clear_error(&error);
}
sprintf(buffer, "unix:abstract=gdbuscxx-%d", counter);
server = g_dbus_server_new_sync(realAddr,
G_DBUS_SERVER_FLAGS_NONE,
guid,
NULL, /* GDBusAuthObserver */
NULL, /* GCancellable */
&error);
}
} else {
server = g_dbus_server_new_sync(realAddr,
G_DBUS_SERVER_FLAGS_NONE,
guid,
NULL, /* GDBusAuthObserver */
NULL, /* GCancellable */
&error);
}
g_free(guid);
if (!server) {
if (err) {
err->set(error);
}
return boost::shared_ptr<DBusServerCXX>();
}
g_dbus_server_start(server);
boost::shared_ptr<DBusServerCXX> res(new DBusServerCXX(server, realAddr));
g_signal_connect(server,
"new-connection",
G_CALLBACK(DBusServerCXX::newConnection),
res.get());
return res;
}
gboolean DBusServerCXX::newConnection(GDBusServer *server, GDBusConnection *newConn, void *data) throw()
{
DBusServerCXX *me = static_cast<DBusServerCXX *>(data);
if (me->m_newConnection) {
GCredentials *credentials;
std::string credString;
credentials = g_dbus_connection_get_peer_credentials(newConn);
if (credentials == NULL) {
credString = "(no credentials received)";
} else {
gchar *s = g_credentials_to_string(credentials);
credString = s;
g_free(s);
}
g_debug("Client connected.\n"
"Peer credentials: %s\n"
"Negotiated capabilities: unix-fd-passing=%d\n",
credString.c_str(),
g_dbus_connection_get_capabilities(newConn) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
try {
DBusConnectionPtr conn(newConn);
me->m_newConnection(*me, conn);
} catch (...) {
g_error("handling new D-Bus connection failed with C++ exception");
}
return TRUE;
} else {
return FALSE;
}
}
DBusServerCXX::DBusServerCXX(GDBusServer *server, const std::string &address) :
m_server(server),
m_address(address)
{
}
}