Skip to content

Commit

Permalink
Multi-interface services
Browse files Browse the repository at this point in the history
Sometimes is it necessary to support multiple interfaces on a single
D-Bus object. This commit extends the `Skeleton` class template to allow
multiple interfaces.

It can similarly be useful to simply rely on the built-in support for
various FreeDesktop interfaces, so the `Skeleton<>` class template
should allow you have _no_ interfaces.
  • Loading branch information
beo-teis committed Apr 10, 2019
1 parent 3f22a24 commit 01dc893
Show file tree
Hide file tree
Showing 17 changed files with 824 additions and 303 deletions.
18 changes: 9 additions & 9 deletions include/simppl/clientside.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct ClientSignalBase
eval_(this, iter);
}

ClientSignalBase(const char* name, StubBase* iface);
ClientSignalBase(const char* name, StubBase* iface, int iface_id);

const char* name() const
{
Expand Down Expand Up @@ -74,8 +74,8 @@ struct ClientSignal : ClientSignalBase

typedef std::function<void(typename CallTraits<T>::param_type...)> function_type;

ClientSignal(const char* name, StubBase* iface)
: ClientSignalBase(name, iface)
ClientSignal(const char* name, StubBase* iface, int iface_id)
: ClientSignalBase(name, iface, iface_id)
{
eval_ = __eval;
}
Expand Down Expand Up @@ -123,7 +123,7 @@ struct ClientPropertyBase
typedef void (*eval_type)(ClientPropertyBase*, DBusMessageIter&);


ClientPropertyBase(const char* name, StubBase* iface);
ClientPropertyBase(const char* name, StubBase* iface, int iface_id);

void eval(DBusMessageIter& iter)
{
Expand Down Expand Up @@ -156,8 +156,8 @@ struct ClientPropertyWritableMixin : ClientPropertyBase
typedef detail::CallbackHolder<function_type, void> holder_type;


ClientPropertyWritableMixin(const char* name, StubBase* iface)
: ClientPropertyBase(name, iface)
ClientPropertyWritableMixin(const char* name, StubBase* iface, int iface_id)
: ClientPropertyBase(name, iface, iface_id)
{
// NOOP
}
Expand Down Expand Up @@ -197,8 +197,8 @@ struct ClientProperty
typedef detail::PropertyCallbackHolder<std::function<void(CallState, arg_type)>, data_type> holder_type;


ClientProperty(const char* name, StubBase* iface)
: base_type(name, iface)
ClientProperty(const char* name, StubBase* iface, int iface_id)
: base_type(name, iface, iface_id)
{
this->eval_ = __eval;
}
Expand Down Expand Up @@ -307,7 +307,7 @@ struct ClientMethod
static_assert(!is_oneway || (is_oneway && std::is_same<return_type, void>::value), "oneway check");


ClientMethod(const char* method_name, StubBase* parent)
ClientMethod(const char* method_name, StubBase* parent, int iface_id)
: method_name_(method_name)
, parent_(parent)
{
Expand Down
37 changes: 37 additions & 0 deletions include/simppl/detail/interposer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef SIMPPL_DETAIL_INTERPOSER_H
#define SIMPPL_DETAIL_INTERPOSER_H

namespace simppl
{

namespace dbus
{

namespace detail
{


template<int Id,
typename AncestorT,
template<typename...> class Method,
template<typename...> class Signal,
template<typename, int> class Property,
template<int, typename, template<typename...> class, template<typename...> class, template<typename, int> class, typename> class I,
template<int, typename, template<typename...> class, template<typename...> class, template<typename, int> class, typename> class... Is>
struct Interposer : I<Id, AncestorT, Method, Signal, Property, Interposer<Id-1, AncestorT, Method, Signal, Property, Is...>> {};

template<typename AncestorT,
template<typename...> class Method,
template<typename...> class Signal,
template<typename, int> class Property,
template<int, typename, template<typename...> class, template<typename...> class, template<typename, int> class, typename> class I>
struct Interposer<0, AncestorT, Method, Signal, Property, I> : I<0, AncestorT, Method, Signal, Property, AncestorT> {};


} // detail

} // dbus

} // simppl

#endif // SIMPPL_DETAIL_INTERPOSER_H
19 changes: 16 additions & 3 deletions include/simppl/detail/util.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef SIMPPL_DETAIL_UTIL_H
#define SIMPPL_DETAIL_UTIL_H

#include <string>
#include <vector>

namespace simppl
{
Expand All @@ -25,10 +27,21 @@ char* create_objectpath(const char* iface, const char* role);
char* create_busname(const char* iface, const char* role);

/**
* @return dbus compatible interface name from mangled c++ name. Must be
* deleted via delete[].
* @return dbus compatible interface names from mangled c++ name.
*/
char* extract_interface(const char* mangled_iface);
std::vector<std::string> extract_interfaces(std::size_t iface_count, const char* mangled_iface_list);

/**
* @return dbus compatible interface name from mangled c++ name.
*/
std::string make_interface_name(const char* begin, const char* end);

/**
* @return a pointer to the N'th interface name given a pointer to the template
* args of interface N-1 or `nullptr` if there are no more interface names.
*/
const char* find_next_interface(const char* template_args);



} // namespace detail
Expand Down
8 changes: 5 additions & 3 deletions include/simppl/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@


#define INTERFACE(iface) \
template<template<typename...> class Method, \
template<int InterfaceID, \
typename AncestorT, \
template<typename...> class Method, \
template<typename...> class Signal, \
template<typename, int Flags=simppl::dbus::Notifying|simppl::dbus::ReadOnly|simppl::dbus::OnChange> class Property, \
typename BaseT> \
struct iface : public BaseT
struct iface : BaseT

#define INIT(what) \
what(# what, this)
what(# what, this, InterfaceID)


#endif // SIMPPL_INTERFACE_H
28 changes: 15 additions & 13 deletions include/simppl/serverside.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct ServerMethodBase

protected:

ServerMethodBase(const char* name, SkeletonBase* iface);
ServerMethodBase(const char* name, SkeletonBase* iface, int iface_id);

~ServerMethodBase();

Expand All @@ -65,7 +65,7 @@ struct ServerMethodBase

struct ServerSignalBase
{
ServerSignalBase(const char* name, SkeletonBase* iface);
ServerSignalBase(const char* name, SkeletonBase* iface, int iface_id);

#if SIMPPL_HAVE_INTROSPECTION
virtual void introspect(std::ostream& os) const = 0;
Expand All @@ -77,22 +77,23 @@ struct ServerSignalBase
~ServerSignalBase() = default;

const char* name_;
int iface_id_;
SkeletonBase* parent_;
};


template<typename... T>
struct ServerSignal : ServerSignalBase
{
ServerSignal(const char* name, SkeletonBase* iface)
: ServerSignalBase(name, iface)
ServerSignal(const char* name, SkeletonBase* iface, int iface_id)
: ServerSignalBase(name, iface, iface_id)
{
// NOOP
}

void notify(typename CallTraits<T>::param_type... args)
{
parent_->send_signal(this->name_, [&](DBusMessageIter& iter){
parent_->send_signal(this->name_, this->iface_id_, [&](DBusMessageIter& iter){
encode(iter, args...);
});
}
Expand Down Expand Up @@ -132,8 +133,8 @@ struct ServerMethod : ServerMethodBase


inline
ServerMethod(const char* name, SkeletonBase* iface)
: ServerMethodBase(name, iface)
ServerMethod(const char* name, SkeletonBase* iface, int iface_id)
: ServerMethodBase(name, iface, iface_id)
{
eval_ = __eval;
}
Expand Down Expand Up @@ -197,7 +198,7 @@ struct ServerPropertyBase
typedef void (*eval_type)(ServerPropertyBase*, DBusMessage*);
typedef void (*eval_set_type)(ServerPropertyBase*, DBusMessageIter&);

ServerPropertyBase(const char* name, SkeletonBase* iface);
ServerPropertyBase(const char* name, SkeletonBase* iface, int iface_id);

void eval(DBusMessage* msg)
{
Expand All @@ -215,6 +216,7 @@ struct ServerPropertyBase

ServerPropertyBase* next_; ///< list hook
const char* name_;
int iface_id_;
SkeletonBase* parent_;

protected:
Expand All @@ -231,8 +233,8 @@ struct BaseProperty : ServerPropertyBase
{
typedef std::function<DataT()> cb_type;

BaseProperty(const char* name, SkeletonBase* iface)
: ServerPropertyBase(name, iface)
BaseProperty(const char* name, SkeletonBase* iface, int iface_id)
: ServerPropertyBase(name, iface, iface_id)
, t_()
{
eval_ = __eval;
Expand All @@ -257,7 +259,7 @@ struct BaseProperty : ServerPropertyBase

void notify(const DataT& data)
{
this->parent_->send_property_change(this->name_, [this, data](DBusMessageIter& iter){
this->parent_->send_property_change(this->name_, this->iface_id_, [this, data](DBusMessageIter& iter){
detail::PropertyCodec<DataT>::encode(iter, data);
});
}
Expand Down Expand Up @@ -314,8 +316,8 @@ struct ServerWritableMixin
template<typename DataT, int Flags>
struct ServerProperty : BaseProperty<DataT>, std::conditional<Flags & ReadWrite, ServerWritableMixin<DataT>, ServerNoopMixin<DataT>>::type
{
ServerProperty(const char* name, SkeletonBase* iface)
: BaseProperty<DataT>(name, iface)
ServerProperty(const char* name, SkeletonBase* iface, int iface_id)
: BaseProperty<DataT>(name, iface, iface_id)
{
if (Flags & ReadWrite)
this->eval_set_ = __eval_set;
Expand Down
42 changes: 32 additions & 10 deletions include/simppl/skeleton.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@


#include <typeinfo>
#include <cxxabi.h>

#include "simppl/skeletonbase.h"
#include "simppl/dispatcher.h"
#include "simppl/serverside.h"
#include "simppl/typelist.h"
#include "simppl/detail/interposer.h"


namespace simppl
Expand All @@ -20,28 +21,32 @@ namespace dbus
void dispatcher_add_skeleton(Dispatcher&, StubBase&);


template<template<template<typename...> class,
template<template<int,
typename,
template<typename...> class,
template<typename,int> class, typename> class IfaceT>
struct Skeleton : IfaceT<ServerMethod, ServerSignal, ServerProperty, SkeletonBase>
template<typename...> class,
template<typename,int> class,
typename> class... Is>
struct Skeleton : detail::Interposer<sizeof...(Is)-1, detail::SizedSkeletonBase<sizeof...(Is)>, ServerMethod, ServerSignal, ServerProperty, Is...>
{
friend struct Dispatcher;

typedef IfaceT<ServerMethod, ServerSignal, ServerProperty, SkeletonBase> interface_type;
using interface_list = make_typelist<Is<0, SkeletonBase, ServerMethod, ServerSignal, ServerProperty, SkeletonBase>...>;

static constexpr std::size_t iface_count = sizeof...(Is);

inline
Skeleton(Dispatcher& disp, const char* role)
: interface_type()
{
this->init(abi::__cxa_demangle(typeid(interface_type).name(), 0, 0, 0), role);
static_assert(iface_count == 1, "Generating bus and object names from a role only works with a single interface");
this->init(typeid(interface_list).name(), role);
dispatcher_add_skeleton(disp, *this);
}

inline
Skeleton(Dispatcher& disp, const char* busname, const char* objectpath)
: interface_type()
Skeleton(Dispatcher& disp, std::string busname, std::string objectpath)
{
this->init(abi::__cxa_demangle(typeid(interface_type).name(), 0, 0, 0), busname, objectpath);
this->init(iface_count, typeid(interface_list).name(), std::move(busname), std::move(objectpath));
dispatcher_add_skeleton(disp, *this);
}

Expand All @@ -51,6 +56,23 @@ struct Skeleton : IfaceT<ServerMethod, ServerSignal, ServerProperty, SkeletonBas
ServerRequestDescriptor current_request_;
};


template<>
struct Skeleton<> : detail::SizedSkeletonBase<0>
{
static constexpr std::size_t iface_count = 0;

Skeleton(Dispatcher& disp, std::string busname, std::string objectpath)
{
this->init(std::move(busname), std::move(objectpath));
dispatcher_add_skeleton(disp, *this);
}

protected:
ServerRequestDescriptor current_request_;
};


} // namespace dbus

} // namespace simppl
Expand Down
Loading

0 comments on commit 01dc893

Please sign in to comment.