blob: 5bf1d1cca25d9f05cf9c2d4ecb4c5c805c5deea6 [file] [log] [blame]
// 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.
#include <functional>
#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) {
// 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()) {
// 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 = [](std::function<void(const Args&...)> callback,
dbus::Signal* signal) {
dbus::MessageReader reader(signal);
DBusParamReader<false, Args...>::Invoke(callback, &reader, nullptr);
// Register our stub handler with D-Bus ObjectProxy.
base::Bind(dbus_signal_callback, signal_callback_wrapper),
} // namespace dbus_utils
} // namespace brillo