summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVernon Mauery <vernon.mauery@linux.intel.com>2018-08-28 08:54:59 -0700
committerVernon Mauery <vernon.mauery@linux.intel.com>2018-08-28 11:17:02 -0700
commit8ce61e4e20a11fbb605cd29f07a820213dbcf91e (patch)
tree5c2d07a39b5d8be2bb1192b8a73de47b733ec4e3
parent387110bdf265b5c4435b740aed7e24c3975c514b (diff)
downloadsdbusplus-8ce61e4e20a11fbb605cd29f07a820213dbcf91e.tar.gz
sdbusplus-8ce61e4e20a11fbb605cd29f07a820213dbcf91e.zip
Allow callback raw access to message
In some cases, the callback may care where the message came from. Allow the callback to receive the raw sdbusplus::message along with the automatically extracted arguments. This means that the registration mechanism as well as the callback mechanism need to be aware of a 'message as a first parameter' situation and behave accordingly. The registration needs to strip the message parameter off in order to expose a correct DBus signature. The callback mechanism needs to strip of the message parameter in order to properly unpack the message, but add it back in before calling apply to execute the function. Tested: Added an example to example/asio-example.cpp and checked to see that it builds. Was able to extract sender from message passed into the IPMI handler. Change-Id: I520e494d3baad34271e748465f30274353554728 Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
-rw-r--r--example/asio-example.cpp8
-rw-r--r--sdbusplus/asio/object_server.hpp88
-rw-r--r--sdbusplus/utility/type_traits.hpp11
3 files changed, 94 insertions, 13 deletions
diff --git a/example/asio-example.cpp b/example/asio-example.cpp
index 82d713e..7477357 100644
--- a/example/asio-example.cpp
+++ b/example/asio-example.cpp
@@ -12,6 +12,11 @@ int foo(int test)
return ++test;
}
+int methodWithMessage(sdbusplus::message::message& m, int test)
+{
+ return ++test;
+}
+
int main()
{
using GetSubTreeType = std::vector<std::pair<
@@ -60,7 +65,6 @@ int main()
{
std::cout << item.first << "\n";
}
-
},
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
@@ -115,6 +119,8 @@ int main()
iface->register_method("TestFunction", foo);
+ iface->register_method("TestMethodWithMessage", methodWithMessage);
+
iface->initialize();
iface->set_property("int", 45);
io.run();
diff --git a/sdbusplus/asio/object_server.hpp b/sdbusplus/asio/object_server.hpp
index 3c0f534..bdd910b 100644
--- a/sdbusplus/asio/object_server.hpp
+++ b/sdbusplus/asio/object_server.hpp
@@ -29,6 +29,12 @@ class callback_set
virtual int set(const boost::any &value) = 0;
};
+template <typename T>
+using FirstArgIsMessage =
+ std::is_same<typename utility::get_first_arg<typename utility::decay_tuple<
+ boost::callable_traits::args_t<T>>::type>::type,
+ message::message>;
+
template <typename CallbackType>
class callback_method_instance : public callback
{
@@ -38,17 +44,8 @@ class callback_method_instance : public callback
}
int call(message::message &m) override
{
- InputTupleType inputArgs;
- if (!utility::read_into_tuple(inputArgs, m))
- {
- return -EINVAL;
- }
-
- auto ret = m.new_method_return();
- callFunction<ResultType>(ret, inputArgs);
- ret.method_return();
- return 1;
- };
+ return expandCall<CallbackType>(m);
+ }
private:
using CallbackSignature = boost::callable_traits::args_t<CallbackType>;
@@ -69,6 +66,42 @@ class callback_method_instance : public callback
{
std::experimental::apply(func_, inputArgs);
}
+ // optional message-first-argument callback
+ template <typename T>
+ std::enable_if_t<FirstArgIsMessage<T>::value, int>
+ expandCall(message::message &m)
+ {
+ using DbusTupleType =
+ typename utility::strip_first_arg<InputTupleType>::type;
+ DbusTupleType dbusArgs;
+ if (!utility::read_into_tuple(dbusArgs, m))
+ {
+ return -EINVAL;
+ }
+
+ auto ret = m.new_method_return();
+ InputTupleType inputArgs =
+ std::tuple_cat(std::forward_as_tuple(std::move(m)), dbusArgs);
+ callFunction<ResultType>(ret, inputArgs);
+ ret.method_return();
+ return 1;
+ };
+ // normal dbus-types-only callback
+ template <typename T>
+ std::enable_if_t<!FirstArgIsMessage<T>::value, int>
+ expandCall(message::message &m)
+ {
+ InputTupleType inputArgs;
+ if (!utility::read_into_tuple(inputArgs, m))
+ {
+ return -EINVAL;
+ }
+
+ auto ret = m.new_method_return();
+ callFunction<ResultType>(ret, inputArgs);
+ ret.method_return();
+ return 1;
+ };
};
template <typename PropertyType, typename CallbackType>
@@ -285,7 +318,38 @@ class dbus_interface
}
template <typename CallbackType>
- bool register_method(const std::string &name, CallbackType &&handler)
+ std::enable_if_t<FirstArgIsMessage<CallbackType>::value, bool>
+ register_method(const std::string &name, CallbackType &&handler)
+ {
+ using CallbackSignature = typename utility::strip_first_arg<
+ boost::callable_traits::args_t<CallbackType>>::type;
+ using InputTupleType =
+ typename utility::decay_tuple<CallbackSignature>::type;
+ using ResultType = boost::callable_traits::return_type_t<CallbackType>;
+
+ if (initialized_)
+ {
+ return false;
+ }
+ static const auto argType = utility::strip_ends(
+ utility::tuple_to_array(message::types::type_id<InputTupleType>()));
+ static const auto resultType =
+ utility::tuple_to_array(message::types::type_id<ResultType>());
+
+ auto nameItr = methodNames_.emplace(methodNames_.end(), name);
+
+ callbacksMethod_[name] =
+ std::make_unique<callback_method_instance<CallbackType>>(
+ std::move(handler));
+
+ vtable_.emplace_back(vtable::method(nameItr->c_str(), argType.data(),
+ resultType.data(), method_handler));
+ return true;
+ }
+
+ template <typename CallbackType>
+ std::enable_if_t<!FirstArgIsMessage<CallbackType>::value, bool>
+ register_method(const std::string &name, CallbackType &&handler)
{
using CallbackSignature = boost::callable_traits::args_t<CallbackType>;
using InputTupleType =
diff --git a/sdbusplus/utility/type_traits.hpp b/sdbusplus/utility/type_traits.hpp
index a88fcfa..e2e0b90 100644
--- a/sdbusplus/utility/type_traits.hpp
+++ b/sdbusplus/utility/type_traits.hpp
@@ -33,6 +33,17 @@ struct strip_first_arg<std::tuple<FirstArg, Rest...>>
using type = std::tuple<Rest...>;
};
+// matching helper class to only return the first type
+template <typename T> struct get_first_arg
+{
+};
+
+template <typename FirstArg, typename... Rest>
+struct get_first_arg<std::tuple<FirstArg, Rest...>>
+{
+ using type = FirstArg;
+};
+
// helper class to remove const and reference from types
template <typename T> struct decay_tuple
{
OpenPOWER on IntegriCloud