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