130477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko// Copyright 2014 The Chromium OS Authors. All rights reserved. 230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko// Use of this source code is governed by a BSD-style license that can be 330477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko// found in the LICENSE file. 430477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 5e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// This file provides internal implementation details of dispatching D-Bus 6e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// method calls to a D-Bus object methods by reading the expected parameter 7e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// values from D-Bus message buffer then invoking a native C++ callback with 8e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// those parameters passed in. If the callback returns a value, that value is 9e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// sent back to the caller of D-Bus method via the response message. 10e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 11e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// This is achieved by redirecting the parsing of parameter values from D-Bus 12e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// message buffer to DBusParamReader helper class. 13e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// DBusParamReader de-serializes the parameter values from the D-Bus message 14e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// and calls the provided native C++ callback with those arguments. 15e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// However it expects the callback with a simple signature like this: 16e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// void callback(Args...); 17f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The method handlers for DBusObject, on the other hand, have one of the 18f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// following signatures: 19f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// void handler(Args...); 20f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// ReturnType handler(Args...); 21f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// bool handler(ErrorPtr* error, Args...); 22a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko// void handler(std::unique_ptr<DBusMethodResponse<T1, T2,...>>, Args...); 23e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// 24e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// To make this all work, we craft a simple callback suitable for 25e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// DBusParamReader using a lambda in DBusInvoker::Invoke() and redirect the call 26e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// to the appropriate method handler using additional data captured by the 27e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko// lambda object. 2830477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 29fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#ifndef LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_INTERNAL_IMPL_H_ 30fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#define LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_INTERNAL_IMPL_H_ 3130477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 3230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <memory> 3330477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <string> 3430477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <type_traits> 3530477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 369ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/data_serialization.h> 379ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_method_response.h> 389ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_param_reader.h> 399ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/dbus_param_writer.h> 409ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/dbus/utils.h> 419ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/errors/error.h> 4230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko#include <dbus/message.h> 4330477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 449ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 4530477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenkonamespace dbus_utils { 4630477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 47f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// This is an abstract base class to allow dispatching a native C++ callback 48f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// method when a corresponding D-Bus method is called. 49f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass DBusInterfaceMethodHandlerInterface { 50f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public: 51f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko virtual ~DBusInterfaceMethodHandlerInterface() = default; 52e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 53f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // Returns true if the method has been handled synchronously (whether or not 54f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // a success or error response message had been sent). 55f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko virtual void HandleMethod(dbus::MethodCall* method_call, 56f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ResponseSender sender) = 0; 57f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko}; 58f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 59f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// This is a special implementation of DBusInterfaceMethodHandlerInterface for 60f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// extremely simple synchronous method handlers that cannot possibly fail 61f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// (that is, they do not send an error response). 62f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The handler is expected to take an arbitrary number of arguments of type 63f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// |Args...| which can contain both inputs (passed in by value or constant 64f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// reference) and outputs (passed in as pointers)... 65f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// It may also return a single value of type R (or could be a void function if 66f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// no return value is to be sent to the caller). If the handler has a return 67f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// value, then it cannot have any output parameters in its parameter list. 68f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The signature of the callback handler is expected to be: 69f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// R(Args...) 70f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkotemplate<typename R, typename... Args> 71f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass SimpleDBusInterfaceMethodHandler 72f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko : public DBusInterfaceMethodHandlerInterface { 73f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public: 74f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 75f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // virtual function is invoked. 76f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko explicit SimpleDBusInterfaceMethodHandler( 77f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko const base::Callback<R(Args...)>& handler) : handler_(handler) {} 78f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 79f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 80f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ResponseSender sender) override { 815e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko DBusMethodResponse<R> method_response(method_call, sender); 82f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko auto invoke_callback = [this, &method_response](const Args&... args) { 83f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko method_response.Return(handler_.Run(args...)); 84e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko }; 85e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 86e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko ErrorPtr param_reader_error; 87f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko dbus::MessageReader reader(method_call); 88f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // The handler is expected a return value, don't allow output parameters. 8905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko if (!DBusParamReader<false, Args...>::Invoke( 9005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko invoke_callback, &reader, ¶m_reader_error)) { 91f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // Error parsing method arguments. 92f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko method_response.ReplyWithError(param_reader_error.get()); 93e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko } 94f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko } 95f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 96f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private: 97f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // C++ callback to be called when a DBus method is dispatched. 98f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko base::Callback<R(Args...)> handler_; 99f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandler); 100f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko}; 101e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 102f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// Specialization of SimpleDBusInterfaceMethodHandlerInterface for 103f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// R=void (methods with no return values). 104f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkotemplate<typename... Args> 105f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass SimpleDBusInterfaceMethodHandler<void, Args...> 106f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko : public DBusInterfaceMethodHandlerInterface { 107f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public: 108f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 109f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // virtual function is invoked. 110f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko explicit SimpleDBusInterfaceMethodHandler( 111f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko const base::Callback<void(Args...)>& handler) : handler_(handler) {} 112f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 113f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 114f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ResponseSender sender) override { 1155e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko DBusMethodResponseBase method_response(method_call, sender); 116f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko auto invoke_callback = [this, &method_response](const Args&... args) { 117f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko handler_.Run(args...); 118f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko auto response = method_response.CreateCustomResponse(); 119f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko dbus::MessageWriter writer(response.get()); 120f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko DBusParamWriter::AppendDBusOutParams(&writer, args...); 121a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko method_response.SendRawResponse(std::move(response)); 122f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko }; 123e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 124f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ErrorPtr param_reader_error; 125f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko dbus::MessageReader reader(method_call); 12605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko if (!DBusParamReader<true, Args...>::Invoke( 12705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko invoke_callback, &reader, ¶m_reader_error)) { 128f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // Error parsing method arguments. 129f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko method_response.ReplyWithError(param_reader_error.get()); 130f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko } 13130477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko } 132f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 133f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private: 134f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // C++ callback to be called when a DBus method is dispatched. 135f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko base::Callback<void(Args...)> handler_; 136f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandler); 137f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko}; 138f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 139f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// An implementation of DBusInterfaceMethodHandlerInterface for simple 140f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// synchronous method handlers that may fail and return an error response 141f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// message. 142f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The handler is expected to take an arbitrary number of arguments of type 143f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// |Args...| which can contain both inputs (passed in by value or constant 144f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// reference) and outputs (passed in as pointers)... 145f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// In case of an error, the handler must return false and set the error details 146f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// into the |error| object provided. 147f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The signature of the callback handler is expected to be: 148f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// bool(ErrorPtr*, Args...) 149f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkotemplate<typename... Args> 150f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass SimpleDBusInterfaceMethodHandlerWithError 151f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko : public DBusInterfaceMethodHandlerInterface { 152f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public: 153f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 154f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // virtual function is invoked. 155f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko explicit SimpleDBusInterfaceMethodHandlerWithError( 156f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko const base::Callback<bool(ErrorPtr*, Args...)>& handler) 15705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko : handler_(handler) {} 158f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 159f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 160f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ResponseSender sender) override { 1615e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko DBusMethodResponseBase method_response(method_call, sender); 162f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko auto invoke_callback = [this, &method_response](const Args&... args) { 163f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ErrorPtr error; 164f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko if (!handler_.Run(&error, args...)) { 165f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko method_response.ReplyWithError(error.get()); 166f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko } else { 167f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko auto response = method_response.CreateCustomResponse(); 168f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko dbus::MessageWriter writer(response.get()); 16990f61fd6ba7ccff59e28b09a3f75e8626b483934Alex Vakulenko DBusParamWriter::AppendDBusOutParams(&writer, args...); 170a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko method_response.SendRawResponse(std::move(response)); 17190f61fd6ba7ccff59e28b09a3f75e8626b483934Alex Vakulenko } 172e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko }; 173e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 174e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko ErrorPtr param_reader_error; 175f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko dbus::MessageReader reader(method_call); 17605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko if (!DBusParamReader<true, Args...>::Invoke( 17705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko invoke_callback, &reader, ¶m_reader_error)) { 178e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko // Error parsing method arguments. 179f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko method_response.ReplyWithError(param_reader_error.get()); 180e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko } 181f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko } 182e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 183f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private: 184f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // C++ callback to be called when a DBus method is dispatched. 185f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko base::Callback<bool(ErrorPtr*, Args...)> handler_; 186f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandlerWithError); 187f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko}; 188e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 1893b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// An implementation of SimpleDBusInterfaceMethodHandlerWithErrorAndMessage 1903b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// which is almost identical to SimpleDBusInterfaceMethodHandlerWithError with 1913b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// the exception that the callback takes an additional parameter - raw D-Bus 1923b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// message used to invoke the method handler. 1933b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The handler is expected to take an arbitrary number of arguments of type 1943b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// |Args...| which can contain both inputs (passed in by value or constant 1953b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// reference) and outputs (passed in as pointers)... 1963b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// In case of an error, the handler must return false and set the error details 1973b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// into the |error| object provided. 1983b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The signature of the callback handler is expected to be: 1993b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// bool(ErrorPtr*, dbus::Message*, Args...) 2003b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkotemplate<typename... Args> 2013b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkoclass SimpleDBusInterfaceMethodHandlerWithErrorAndMessage 2023b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko : public DBusInterfaceMethodHandlerInterface { 2033b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko public: 2043b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 2053b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // virtual function is invoked. 2063b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko explicit SimpleDBusInterfaceMethodHandlerWithErrorAndMessage( 2073b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko const base::Callback<bool(ErrorPtr*, dbus::Message*, Args...)>& handler) 2083b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko : handler_(handler) {} 2093b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 2103b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 2113b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko ResponseSender sender) override { 2123b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko DBusMethodResponseBase method_response(method_call, sender); 2133b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko auto invoke_callback = 2143b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko [this, method_call, &method_response](const Args&... args) { 2153b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko ErrorPtr error; 2163b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko if (!handler_.Run(&error, method_call, args...)) { 2173b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko method_response.ReplyWithError(error.get()); 2183b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko } else { 2193b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko auto response = method_response.CreateCustomResponse(); 2203b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko dbus::MessageWriter writer(response.get()); 2213b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko DBusParamWriter::AppendDBusOutParams(&writer, args...); 222a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko method_response.SendRawResponse(std::move(response)); 2233b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko } 2243b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko }; 2253b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 2263b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko ErrorPtr param_reader_error; 2273b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko dbus::MessageReader reader(method_call); 2283b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko if (!DBusParamReader<true, Args...>::Invoke( 2293b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko invoke_callback, &reader, ¶m_reader_error)) { 2303b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // Error parsing method arguments. 2313b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko method_response.ReplyWithError(param_reader_error.get()); 2323b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko } 2333b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko } 2343b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 2353b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko private: 2363b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // C++ callback to be called when a DBus method is dispatched. 2373b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko base::Callback<bool(ErrorPtr*, dbus::Message*, Args...)> handler_; 2383b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko DISALLOW_COPY_AND_ASSIGN(SimpleDBusInterfaceMethodHandlerWithErrorAndMessage); 2393b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko}; 2403b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 241f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// An implementation of DBusInterfaceMethodHandlerInterface for more generic 242f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// (and possibly asynchronous) method handlers. The handler is expected 243f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// to take an arbitrary number of input arguments of type |Args...| and send 244f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// the method call response (including a possible error response) using 245f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// the provided DBusMethodResponse object. 246f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// The signature of the callback handler is expected to be: 247a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko// void(std::unique_ptr<DBusMethodResponse<RetTypes...>, Args...) 2485e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenkotemplate<typename Response, typename... Args> 249f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass DBusInterfaceMethodHandler : public DBusInterfaceMethodHandlerInterface { 250f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public: 251f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 252f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // virtual function is invoked. 253f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko explicit DBusInterfaceMethodHandler( 254a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko const base::Callback<void(std::unique_ptr<Response>, Args...)>& handler) 25505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko : handler_(handler) {} 256f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 257f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // This method forwards the call to |handler_| after extracting the required 258f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // arguments from the DBus message buffer specified in |method_call|. 259f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // The output parameters of |handler_| (if any) are sent back to the called. 260f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 261f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ResponseSender sender) override { 262f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko auto invoke_callback = [this, method_call, &sender](const Args&... args) { 263a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko std::unique_ptr<Response> response(new Response(method_call, sender)); 264a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko handler_.Run(std::move(response), args...); 265e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko }; 266e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko 267e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko ErrorPtr param_reader_error; 268f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko dbus::MessageReader reader(method_call); 26905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko if (!DBusParamReader<false, Args...>::Invoke( 27005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko invoke_callback, &reader, ¶m_reader_error)) { 271f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // Error parsing method arguments. 2725e16f0659e1a77e5b81a3d89e251f18c71e239cdAlex Vakulenko DBusMethodResponseBase method_response(method_call, sender); 273f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko method_response.ReplyWithError(param_reader_error.get()); 274e46e51f0af1c4b1f49da9019a2d71e96e484273bAlex Vakulenko } 27530477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko } 276f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 277f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private: 278f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // C++ callback to be called when a D-Bus method is dispatched. 279a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko base::Callback<void(std::unique_ptr<Response>, Args...)> handler_; 280f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 281f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(DBusInterfaceMethodHandler); 282f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko}; 283f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 2843b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// An implementation of DBusInterfaceMethodHandlerWithMessage which is almost 2853b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// identical to AddSimpleMethodHandlerWithError with the exception that the 2863b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// callback takes an additional parameter - raw D-Bus message. 2873b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The handler is expected to take an arbitrary number of input arguments of 2883b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// type |Args...| and send the method call response (including a possible error 2893b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// response) using the provided DBusMethodResponse object. 2903b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko// The signature of the callback handler is expected to be: 291a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko// void(std::unique_ptr<DBusMethodResponse<RetTypes...>, dbus::Message*, 292a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko// Args...); 2933b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkotemplate<typename Response, typename... Args> 2943b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenkoclass DBusInterfaceMethodHandlerWithMessage 2953b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko : public DBusInterfaceMethodHandlerInterface { 2963b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko public: 2973b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 2983b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // virtual function is invoked. 2993b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko explicit DBusInterfaceMethodHandlerWithMessage( 300a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko const base::Callback<void(std::unique_ptr<Response>, dbus::Message*, 3013b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko Args...)>& handler) 3023b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko : handler_(handler) {} 3033b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 3043b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // This method forwards the call to |handler_| after extracting the required 3053b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // arguments from the DBus message buffer specified in |method_call|. 3063b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // The output parameters of |handler_| (if any) are sent back to the called. 3073b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 3083b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko ResponseSender sender) override { 3093b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko auto invoke_callback = [this, method_call, &sender](const Args&... args) { 310a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko std::unique_ptr<Response> response(new Response(method_call, sender)); 311a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko handler_.Run(std::move(response), method_call, args...); 3123b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko }; 3133b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 3143b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko ErrorPtr param_reader_error; 3153b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko dbus::MessageReader reader(method_call); 3163b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko if (!DBusParamReader<false, Args...>::Invoke( 3173b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko invoke_callback, &reader, ¶m_reader_error)) { 3183b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // Error parsing method arguments. 3193b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko DBusMethodResponseBase method_response(method_call, sender); 3203b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko method_response.ReplyWithError(param_reader_error.get()); 3213b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko } 3223b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko } 3233b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 3243b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko private: 3253b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko // C++ callback to be called when a D-Bus method is dispatched. 326a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko base::Callback<void(std::unique_ptr<Response>, 327a4df79e294e678591cb94e09c73ab41a62086492Alex Vakulenko dbus::Message*, Args...)> handler_; 3283b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 3293b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko DISALLOW_COPY_AND_ASSIGN(DBusInterfaceMethodHandlerWithMessage); 3303b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko}; 3313b34ec47a64fb4adde0f0bb486a4f2f8033b49b8Alex Vakulenko 332f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// An implementation of DBusInterfaceMethodHandlerInterface that has custom 333f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// processing of both input and output parameters. This class is used by 334f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// DBusObject::AddRawMethodHandler and expects the callback to be of the 335f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// following signature: 336f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// void(dbus::MethodCall*, ResponseSender) 337f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// It will be up to the callback to parse the input parameters from the 338f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko// message buffer and construct the D-Bus Response object. 339f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenkoclass RawDBusInterfaceMethodHandler 340f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko : public DBusInterfaceMethodHandlerInterface { 341f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko public: 342f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // A constructor that takes a |handler| to be called when HandleMethod() 343f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // virtual function is invoked. 344253b5b6d35d47ed6b58b0ca1042b7455b0e2fdb2Chih-Hung Hsieh explicit RawDBusInterfaceMethodHandler( 345f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko const base::Callback<void(dbus::MethodCall*, ResponseSender)>& handler) 34605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko : handler_(handler) {} 347f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 348f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko void HandleMethod(dbus::MethodCall* method_call, 349f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko ResponseSender sender) override { 350f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko handler_.Run(method_call, sender); 351f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko } 352f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 353f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko private: 354f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko // C++ callback to be called when a D-Bus method is dispatched. 355f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko base::Callback<void(dbus::MethodCall*, ResponseSender)> handler_; 356f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko 357f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(RawDBusInterfaceMethodHandler); 358f437e3b367869af7cb5a53153284566164b48a7cAlex Vakulenko}; 35930477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 36030477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko} // namespace dbus_utils 3619ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 36230477dda841e0b06ace6ef09061e0ae55617916eAlex Vakulenko 363fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#endif // LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_INTERNAL_IMPL_H_ 364