1 /* 2 * Copyright (c) 2019, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for a d-bus object. 32 */ 33 34 #ifndef OTBR_DBUS_DBUS_OBJECT_HPP_ 35 #define OTBR_DBUS_DBUS_OBJECT_HPP_ 36 37 #ifndef OTBR_LOG_TAG 38 #define OTBR_LOG_TAG "DBUS" 39 #endif 40 41 #include <functional> 42 #include <memory> 43 #include <string> 44 #include <unordered_map> 45 46 #include <dbus/dbus.h> 47 48 #include "common/code_utils.hpp" 49 #include "common/types.hpp" 50 #include "dbus/common/constants.hpp" 51 #include "dbus/common/dbus_message_dump.hpp" 52 #include "dbus/common/dbus_message_helper.hpp" 53 #include "dbus/common/dbus_resources.hpp" 54 #include "dbus/server/dbus_request.hpp" 55 56 namespace otbr { 57 namespace DBus { 58 59 /** 60 * This class is a base class for implementing a d-bus object. 61 * 62 */ 63 class DBusObject : private NonCopyable 64 { 65 public: 66 using MethodHandlerType = std::function<void(DBusRequest &)>; 67 68 using PropertyHandlerType = std::function<otError(DBusMessageIter &)>; 69 70 /** 71 * The constructor of a d-bus object. 72 * 73 * @param[in] aConnection The dbus-connection the object bounds to. 74 * @param[in] aObjectPath The path of the object. 75 * 76 */ 77 DBusObject(DBusConnection *aConnection, const std::string &aObjectPath); 78 79 /** 80 * This method initializes the d-bus object. 81 * 82 * This method will register the object to the d-bus library. 83 * 84 * @retval OTBR_ERROR_NONE Successfully registered the object. 85 * @retval OTBR_ERROR_DBUS Failed to ragister an object. 86 * 87 */ 88 virtual otbrError Init(void); 89 90 /** 91 * This method registers the method handler. 92 * 93 * @param[in] aInterfaceName The interface name. 94 * @param[in] aMethodName The method name. 95 * @param[in] aHandler The method handler. 96 * 97 */ 98 void RegisterMethod(const std::string & aInterfaceName, 99 const std::string & aMethodName, 100 const MethodHandlerType &aHandler); 101 102 /** 103 * This method registers the get handler for a property. 104 * 105 * @param[in] aInterfaceName The interface name. 106 * @param[in] aPropertyName The property name. 107 * @param[in] aHandler The method handler. 108 * 109 */ 110 virtual void RegisterGetPropertyHandler(const std::string & aInterfaceName, 111 const std::string & aPropertyName, 112 const PropertyHandlerType &aHandler); 113 114 /** 115 * This method registers the set handler for a property. 116 * 117 * @param[in] aInterfaceName The interface name. 118 * @param[in] aPropertyName The property name. 119 * @param[in] aHandler The method handler. 120 * 121 */ 122 virtual void RegisterSetPropertyHandler(const std::string & aInterfaceName, 123 const std::string & aPropertyName, 124 const PropertyHandlerType &aHandler); 125 126 /** 127 * This method sends a signal. 128 * 129 * @param[in] aInterfaceName The interface name. 130 * @param[in] aSignalName The signal name. 131 * @param[in] aArgs The tuple to be encoded into the signal. 132 * 133 * @retval OTBR_ERROR_NONE Signal successfully sent. 134 * @retval OTBR_ERROR_DBUS Failed to send the signal. 135 * 136 */ 137 template <typename... FieldTypes> Signal(const std::string & aInterfaceName,const std::string & aSignalName,const std::tuple<FieldTypes...> & aArgs)138 otbrError Signal(const std::string & aInterfaceName, 139 const std::string & aSignalName, 140 const std::tuple<FieldTypes...> &aArgs) 141 { 142 UniqueDBusMessage signalMsg = NewSignalMessage(aInterfaceName, aSignalName); 143 otbrError error = OTBR_ERROR_NONE; 144 145 VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS); 146 SuccessOrExit(error = otbr::DBus::TupleToDBusMessage(*signalMsg, aArgs)); 147 148 VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS); 149 150 exit: 151 return error; 152 } 153 154 /** 155 * This method sends a property changed signal. 156 * 157 * @param[in] aInterfaceName The interface name. 158 * @param[in] aPropertyName The property name. 159 * @param[in] aValue New value of the property. 160 * 161 * @retval OTBR_ERROR_NONE Signal successfully sent. 162 * @retval OTBR_ERROR_DBUS Failed to send the signal. 163 * 164 */ 165 template <typename ValueType> SignalPropertyChanged(const std::string & aInterfaceName,const std::string & aPropertyName,const ValueType & aValue)166 otbrError SignalPropertyChanged(const std::string &aInterfaceName, 167 const std::string &aPropertyName, 168 const ValueType & aValue) 169 { 170 UniqueDBusMessage signalMsg = NewSignalMessage(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL); 171 DBusMessageIter iter, subIter, dictEntryIter; 172 otbrError error = OTBR_ERROR_NONE; 173 174 VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS); 175 dbus_message_iter_init_append(signalMsg.get(), &iter); 176 177 // interface_name 178 VerifyOrExit(DBusMessageEncode(&iter, aInterfaceName) == OTBR_ERROR_NONE, error = OTBR_ERROR_DBUS); 179 180 // changed_properties 181 VerifyOrExit(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 182 "{" DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING "}", 183 &subIter), 184 error = OTBR_ERROR_DBUS); 185 VerifyOrExit(dbus_message_iter_open_container(&subIter, DBUS_TYPE_DICT_ENTRY, nullptr, &dictEntryIter), 186 error = OTBR_ERROR_DBUS); 187 188 SuccessOrExit(error = DBusMessageEncode(&dictEntryIter, aPropertyName)); 189 SuccessOrExit(error = DBusMessageEncodeToVariant(&dictEntryIter, aValue)); 190 191 VerifyOrExit(dbus_message_iter_close_container(&subIter, &dictEntryIter), error = OTBR_ERROR_DBUS); 192 VerifyOrExit(dbus_message_iter_close_container(&iter, &subIter), error = OTBR_ERROR_DBUS); 193 194 // invalidated_properties 195 SuccessOrExit(error = DBusMessageEncode(&iter, std::vector<std::string>())); 196 197 if (otbrLogGetLevel() >= OTBR_LOG_DEBUG) 198 { 199 otbrLogDebug("Signal %s.%s", aInterfaceName.c_str(), aPropertyName.c_str()); 200 DumpDBusMessage(*signalMsg); 201 } 202 203 VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS); 204 205 exit: 206 return error; 207 } 208 209 /** 210 * The destructor of a d-bus object. 211 * 212 */ 213 virtual ~DBusObject(void); 214 215 private: 216 void GetAllPropertiesMethodHandler(DBusRequest &aRequest); 217 void GetPropertyMethodHandler(DBusRequest &aRequest); 218 void SetPropertyMethodHandler(DBusRequest &aRequest); 219 220 static DBusHandlerResult sMessageHandler(DBusConnection *aConnection, DBusMessage *aMessage, void *aData); 221 DBusHandlerResult MessageHandler(DBusConnection *aConnection, DBusMessage *aMessage); 222 223 UniqueDBusMessage NewSignalMessage(const std::string &aInterfaceName, const std::string &aSignalName); 224 225 std::unordered_map<std::string, MethodHandlerType> mMethodHandlers; 226 std::unordered_map<std::string, std::unordered_map<std::string, PropertyHandlerType>> mGetPropertyHandlers; 227 std::unordered_map<std::string, PropertyHandlerType> mSetPropertyHandlers; 228 DBusConnection * mConnection; 229 std::string mObjectPath; 230 }; 231 232 } // namespace DBus 233 } // namespace otbr 234 235 #endif // OTBR_DBUS_DBUS_SERVER_HPP_ 236