1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li
5*1a96fba6SXin Li #ifndef LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_
6*1a96fba6SXin Li #define LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_
7*1a96fba6SXin Li
8*1a96fba6SXin Li #include <functional>
9*1a96fba6SXin Li #include <string>
10*1a96fba6SXin Li #include <utility>
11*1a96fba6SXin Li
12*1a96fba6SXin Li #include <base/bind.h>
13*1a96fba6SXin Li #include <brillo/dbus/dbus_param_reader.h>
14*1a96fba6SXin Li #include <dbus/message.h>
15*1a96fba6SXin Li #include <dbus/object_proxy.h>
16*1a96fba6SXin Li
17*1a96fba6SXin Li namespace brillo {
18*1a96fba6SXin Li namespace dbus_utils {
19*1a96fba6SXin Li
20*1a96fba6SXin Li // brillo::dbus_utils::ConnectToSignal() is a helper function similar to
21*1a96fba6SXin Li // dbus::ObjectProxy::ConnectToSignal() but the |signal_callback| is an actual
22*1a96fba6SXin Li // C++ signal handler with expected signal parameters as native method args.
23*1a96fba6SXin Li //
24*1a96fba6SXin Li // brillo::dbus_utils::ConnectToSignal() actually registers a stub signal
25*1a96fba6SXin Li // handler with D-Bus which has a standard signature that matches
26*1a96fba6SXin Li // dbus::ObjectProxy::SignalCallback.
27*1a96fba6SXin Li //
28*1a96fba6SXin Li // When a D-Bus signal is emitted, the stub handler is invoked, which unpacks
29*1a96fba6SXin Li // the expected parameters from dbus::Signal message and then calls
30*1a96fba6SXin Li // |signal_callback| with unpacked arguments.
31*1a96fba6SXin Li //
32*1a96fba6SXin Li // If the signal message doesn't contain correct number or types of arguments,
33*1a96fba6SXin Li // an error message is logged to the system log and the signal is ignored
34*1a96fba6SXin Li // (|signal_callback| is not invoked).
35*1a96fba6SXin Li template <typename... Args>
ConnectToSignal(::dbus::ObjectProxy * object_proxy,const std::string & interface_name,const std::string & signal_name,base::Callback<void (Args...)> signal_callback,::dbus::ObjectProxy::OnConnectedCallback on_connected_callback)36*1a96fba6SXin Li void ConnectToSignal(
37*1a96fba6SXin Li ::dbus::ObjectProxy* object_proxy,
38*1a96fba6SXin Li const std::string& interface_name,
39*1a96fba6SXin Li const std::string& signal_name,
40*1a96fba6SXin Li base::Callback<void(Args...)> signal_callback,
41*1a96fba6SXin Li ::dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
42*1a96fba6SXin Li // DBusParamReader::Invoke() needs a functor object, not a base::Callback.
43*1a96fba6SXin Li // Wrap the callback with lambda so we can redirect the call.
44*1a96fba6SXin Li auto signal_callback_wrapper = [signal_callback](const Args&... args) {
45*1a96fba6SXin Li if (!signal_callback.is_null()) {
46*1a96fba6SXin Li signal_callback.Run(args...);
47*1a96fba6SXin Li }
48*1a96fba6SXin Li };
49*1a96fba6SXin Li
50*1a96fba6SXin Li // Raw signal handler stub method. When called, unpacks the signal arguments
51*1a96fba6SXin Li // from |signal| message buffer and redirects the call to
52*1a96fba6SXin Li // |signal_callback_wrapper| which, in turn, would call the user-provided
53*1a96fba6SXin Li // |signal_callback|.
54*1a96fba6SXin Li auto dbus_signal_callback = [](std::function<void(const Args&...)> callback,
55*1a96fba6SXin Li ::dbus::Signal* signal) {
56*1a96fba6SXin Li ::dbus::MessageReader reader(signal);
57*1a96fba6SXin Li DBusParamReader<false, Args...>::Invoke(callback, &reader, nullptr);
58*1a96fba6SXin Li };
59*1a96fba6SXin Li
60*1a96fba6SXin Li // Register our stub handler with D-Bus ObjectProxy.
61*1a96fba6SXin Li object_proxy->ConnectToSignal(
62*1a96fba6SXin Li interface_name, signal_name,
63*1a96fba6SXin Li base::Bind(dbus_signal_callback, signal_callback_wrapper),
64*1a96fba6SXin Li std::move(on_connected_callback));
65*1a96fba6SXin Li }
66*1a96fba6SXin Li
67*1a96fba6SXin Li } // namespace dbus_utils
68*1a96fba6SXin Li } // namespace brillo
69*1a96fba6SXin Li
70*1a96fba6SXin Li #endif // LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_
71