syncevolution/src/gdbusxx/gdbus-cxx.h
Patrick Ohly db3f5d69db GDBus GIO: more flexible SignalWatch
Working with obexd 0.47's Transfer object depends on path prefix
filtering of signals to be efficient. This patch adds that support in
the GDBus C++ bindings, together with some documentation on how to
use it.

It also allows relaxing the signal matching by interpreting empty
strings as "match any".

Finally it adds support for passing of sender, path, interface and
member (= signal name) information to the user of the D-Bus
binding. This is necessary because a handler with wildcards for
matching cannot know the actual values unless they are passed to the
callback explicitly. This was not possible at all before for signals
(because extracting that information relied on a message pointer,
which wasn't set while decoding signal messages) and limited to just
the sender in method implementations.

Besides in functionality, GDBus for GIO and for libdbus now also
differ slightly in their API. In order to pass meta data about a
signal into the demarshalling get() methods, they have to be stored in
ExtractArgs first and passed to get() via that struct, which is an
interface change.

Derived code which extends marshalling/demarshalling needs to be
adapted accordingly. Allowing some ifdefs elsewhere seems simpler than
adapting GDBus for libdbus. Those ifdefs can be removed once libdbus
support is no longer needed.

The patch relaxes access control to DBusObject and DBusRemoteObject
because that simplifies the code which works better with std::string.

Traditionally the sender of a signal was not checked. This is probably
related to unsolved questions like "should watching org.foo.bar follow
owner changes", but not doing any checking is just not right
either. Not fixed in this patch.
2012-09-26 08:36:35 +02:00

207 lines
5.9 KiB
C++

/*
* Copyright (C) 2009 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
*/
#ifndef INCL_GDBUS_CXX
#define INCL_GDBUS_CXX
#include <string>
#include <stdexcept>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
namespace GDBusCXX {
/**
* An exception class which can be thrown to create
* specific D-Bus exception on the bus.
*/
class dbus_error : public std::runtime_error
{
public:
/**
* @param dbus_name the D-Bus error name, like "org.example.error.Invalid"
* @param what a more detailed description
*/
dbus_error(const std::string &dbus_name, const std::string &what) :
std::runtime_error(what),
m_dbus_name(dbus_name)
{}
~dbus_error() throw() {}
const std::string &dbusName() const { return m_dbus_name; }
private:
std::string m_dbus_name;
};
/**
* Special parameter type that identifies a D-Bus bus address. A string in practice.
*/
class Caller_t : public std::string
{
public:
Caller_t() {}
template <class T> Caller_t(T val) : std::string(val) {}
template <class T> Caller_t &operator = (T val) { assign(val); return *this; }
};
/**
* Special parameter type that identifies the path in a D-Bus message. A string in practice.
*/
class Path_t : public std::string
{
public:
Path_t() {}
template <class T> Path_t(T val) : std::string(val) {}
template <class T> Path_t &operator = (T val) { assign(val); return *this; }
};
/**
* Special parameter type that identifies the interface in a D-Bus message. A string in practice.
*/
class Interface_t : public std::string
{
public:
Interface_t() {}
template <class T> Interface_t(T val) : std::string(val) {}
template <class T> Interface_t &operator = (T val) { assign(val); return *this; }
};
/**
* Special parameter type that identifies the member of an interface
* (= signal or method) in a D-Bus message. A string in practice.
*/
class Member_t : public std::string
{
public:
Member_t() {}
template <class T> Member_t(T val) : std::string(val) {}
template <class T> Member_t &operator = (T val) { assign(val); return *this; }
};
class Watch;
/**
* Call object which needs to be called with the results
* of an asynchronous method call. So instead of
* "int foo()" one would implement
* "void foo(Result1<int> > *r)"
* and after foo has returned, call r->done(res). Use const
* references as type for complex results.
*
* A Result instance can be copied, but only called once.
*/
class Result
{
public:
virtual ~Result() {}
/** report failure to caller */
virtual void failed(const dbus_error &error) = 0;
/**
* Calls the given callback once when the peer that the result
* would be delivered to disconnects. The callback will also be
* called if the peer is already gone by the time that the watch
* is requested.
*
* Alternatively a method can ask to get called with a life Watch
* by specifying "const boost::shared_ptr<Watch> &" as parameter
* and then calling its setCallback().
*/
virtual Watch *createWatch(const boost::function<void (void)> &callback) = 0;
};
class Result0 : virtual public Result
{
public:
/** tell caller that we are done */
virtual void done() = 0;
};
template <typename A1>
class Result1 : virtual public Result
{
public:
/** return result to caller */
virtual void done(A1 a1) = 0;
};
template <typename A1, typename A2>
struct Result2 : virtual public Result
{
virtual void done(A1 a1, A2 a2) = 0;
};
template <typename A1, typename A2, typename A3>
struct Result3 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3) = 0;
};
template <typename A1, typename A2, typename A3, typename A4>
struct Result4 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4) = 0;
};
template <typename A1, typename A2, typename A3, typename A4, typename A5>
struct Result5 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) = 0;
};
template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6>
struct Result6 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) = 0;
};
template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7>
struct Result7 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) = 0;
};
template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8>
struct Result8 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) = 0;
};
template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8, typename A9>
struct Result9 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) = 0;
};
template <typename A1, typename A2, typename A3, typename A4, typename A5,
typename A6, typename A7, typename A8, typename A9, typename A10>
struct Result10 : virtual public Result
{
virtual void done(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) = 0;
};
} // namespace GDBusCXX
#endif // INCL_GDBUS_CXX