// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_
#define LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_
#include <string>
#include <brillo/bind_lambda.h>
#include <brillo/dbus/dbus_param_reader.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
namespace brillo {
namespace dbus_utils {
// brillo::dbus_utils::ConnectToSignal() is a helper function similar to
// dbus::ObjectProxy::ConnectToSignal() but the |signal_callback| is an actual
// C++ signal handler with expected signal parameters as native method args.
//
// brillo::dbus_utils::ConnectToSignal() actually registers a stub signal
// handler with D-Bus which has a standard signature that matches
// dbus::ObjectProxy::SignalCallback.
//
// When a D-Bus signal is emitted, the stub handler is invoked, which unpacks
// the expected parameters from dbus::Signal message and then calls
// |signal_callback| with unpacked arguments.
//
// If the signal message doesn't contain correct number or types of arguments,
// an error message is logged to the system log and the signal is ignored
// (|signal_callback| is not invoked).
template<typename... Args>
void 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) {
// Raw signal handler stub method. When called, unpacks the signal arguments
// from |signal| message buffer and redirects the call to
// |signal_callback_wrapper| which, in turn, would call the user-provided
// |signal_callback|.
auto dbus_signal_callback = [](
const base::Callback<void(Args...)>& signal_callback,
dbus::Signal* signal) {
// DBusParamReader::Invoke() needs a functor object, not a base::Callback.
// Wrap the callback with lambda so we can redirect the call.
auto signal_callback_wrapper = [signal_callback](const Args&... args) {
if (!signal_callback.is_null()) {
signal_callback.Run(args...);
}
};
dbus::MessageReader reader(signal);
DBusParamReader<false, Args...>::Invoke(
signal_callback_wrapper, &reader, nullptr);
};
// Register our stub handler with D-Bus ObjectProxy.
object_proxy->ConnectToSignal(interface_name,
signal_name,
base::Bind(dbus_signal_callback, signal_callback),
on_connected_callback);
}
} // namespace dbus_utils
} // namespace brillo
#endif // LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_