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 #include "openthread-br/config.h" 38 39 #ifndef OTBR_LOG_TAG 40 #define OTBR_LOG_TAG "DBUS" 41 #endif 42 43 #include <functional> 44 #include <memory> 45 #include <string> 46 #include <unordered_map> 47 48 #include <dbus/dbus.h> 49 50 #include "common/code_utils.hpp" 51 #include "common/types.hpp" 52 #include "dbus/common/constants.hpp" 53 #include "dbus/common/dbus_message_dump.hpp" 54 #include "dbus/common/dbus_message_helper.hpp" 55 #include "dbus/common/dbus_resources.hpp" 56 #include "dbus/server/dbus_request.hpp" 57 58 namespace otbr { 59 namespace DBus { 60 61 /** 62 * This class is a base class for implementing a d-bus object. 63 * 64 */ 65 class DBusObject : private NonCopyable 66 { 67 public: 68 using MethodHandlerType = std::function<void(DBusRequest &)>; 69 70 using PropertyHandlerType = std::function<otError(DBusMessageIter &)>; 71 72 /** 73 * The constructor of a d-bus object. 74 * 75 * @param[in] aConnection The dbus-connection the object bounds to. 76 * @param[in] aObjectPath The path of the object. 77 * 78 */ 79 DBusObject(DBusConnection *aConnection, const std::string &aObjectPath); 80 81 /** 82 * This method initializes the d-bus object. 83 * 84 * This method will register the object to the d-bus library. 85 * 86 * @retval OTBR_ERROR_NONE Successfully registered the object. 87 * @retval OTBR_ERROR_DBUS Failed to ragister an object. 88 * 89 */ 90 virtual otbrError Init(void); 91 92 /** 93 * This method registers the method handler. 94 * 95 * @param[in] aInterfaceName The interface name. 96 * @param[in] aMethodName The method name. 97 * @param[in] aHandler The method handler. 98 * 99 */ 100 void RegisterMethod(const std::string &aInterfaceName, 101 const std::string &aMethodName, 102 const MethodHandlerType &aHandler); 103 104 /** 105 * This method registers the get handler for a property. 106 * 107 * @param[in] aInterfaceName The interface name. 108 * @param[in] aPropertyName The property name. 109 * @param[in] aHandler The method handler. 110 * 111 */ 112 virtual void RegisterGetPropertyHandler(const std::string &aInterfaceName, 113 const std::string &aPropertyName, 114 const PropertyHandlerType &aHandler); 115 116 /** 117 * This method registers the set handler for a property. 118 * 119 * @param[in] aInterfaceName The interface name. 120 * @param[in] aPropertyName The property name. 121 * @param[in] aHandler The method handler. 122 * 123 */ 124 virtual void RegisterSetPropertyHandler(const std::string &aInterfaceName, 125 const std::string &aPropertyName, 126 const PropertyHandlerType &aHandler); 127 128 /** 129 * This method sends a signal. 130 * 131 * @param[in] aInterfaceName The interface name. 132 * @param[in] aSignalName The signal name. 133 * @param[in] aArgs The tuple to be encoded into the signal. 134 * 135 * @retval OTBR_ERROR_NONE Signal successfully sent. 136 * @retval OTBR_ERROR_DBUS Failed to send the signal. 137 * 138 */ 139 template <typename... FieldTypes> Signal(const std::string & aInterfaceName,const std::string & aSignalName,const std::tuple<FieldTypes...> & aArgs)140 otbrError Signal(const std::string &aInterfaceName, 141 const std::string &aSignalName, 142 const std::tuple<FieldTypes...> &aArgs) 143 { 144 UniqueDBusMessage signalMsg = NewSignalMessage(aInterfaceName, aSignalName); 145 otbrError error = OTBR_ERROR_NONE; 146 147 VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS); 148 SuccessOrExit(error = otbr::DBus::TupleToDBusMessage(*signalMsg, aArgs)); 149 150 VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS); 151 152 exit: 153 return error; 154 } 155 156 /** 157 * This method sends a property changed signal. 158 * 159 * @param[in] aInterfaceName The interface name. 160 * @param[in] aPropertyName The property name. 161 * @param[in] aValue New value of the property. 162 * 163 * @retval OTBR_ERROR_NONE Signal successfully sent. 164 * @retval OTBR_ERROR_DBUS Failed to send the signal. 165 * 166 */ 167 template <typename ValueType> SignalPropertyChanged(const std::string & aInterfaceName,const std::string & aPropertyName,const ValueType & aValue)168 otbrError SignalPropertyChanged(const std::string &aInterfaceName, 169 const std::string &aPropertyName, 170 const ValueType &aValue) 171 { 172 UniqueDBusMessage signalMsg = NewSignalMessage(DBUS_INTERFACE_PROPERTIES, DBUS_PROPERTIES_CHANGED_SIGNAL); 173 DBusMessageIter iter, subIter, dictEntryIter; 174 otbrError error = OTBR_ERROR_NONE; 175 176 VerifyOrExit(signalMsg != nullptr, error = OTBR_ERROR_DBUS); 177 dbus_message_iter_init_append(signalMsg.get(), &iter); 178 179 // interface_name 180 VerifyOrExit(DBusMessageEncode(&iter, aInterfaceName) == OTBR_ERROR_NONE, error = OTBR_ERROR_DBUS); 181 182 // changed_properties 183 VerifyOrExit(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 184 "{" DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING "}", 185 &subIter), 186 error = OTBR_ERROR_DBUS); 187 VerifyOrExit(dbus_message_iter_open_container(&subIter, DBUS_TYPE_DICT_ENTRY, nullptr, &dictEntryIter), 188 error = OTBR_ERROR_DBUS); 189 190 SuccessOrExit(error = DBusMessageEncode(&dictEntryIter, aPropertyName)); 191 SuccessOrExit(error = DBusMessageEncodeToVariant(&dictEntryIter, aValue)); 192 193 VerifyOrExit(dbus_message_iter_close_container(&subIter, &dictEntryIter), error = OTBR_ERROR_DBUS); 194 VerifyOrExit(dbus_message_iter_close_container(&iter, &subIter), error = OTBR_ERROR_DBUS); 195 196 // invalidated_properties 197 SuccessOrExit(error = DBusMessageEncode(&iter, std::vector<std::string>())); 198 199 if (otbrLogGetLevel() >= OTBR_LOG_DEBUG) 200 { 201 otbrLogDebug("Signal %s.%s", aInterfaceName.c_str(), aPropertyName.c_str()); 202 DumpDBusMessage(*signalMsg); 203 } 204 205 VerifyOrExit(dbus_connection_send(mConnection, signalMsg.get(), nullptr), error = OTBR_ERROR_DBUS); 206 207 exit: 208 return error; 209 } 210 211 /** 212 * The destructor of a d-bus object. 213 * 214 */ 215 virtual ~DBusObject(void); 216 217 /** 218 * Sends all outgoing messages, blocks until the message queue is empty. 219 * 220 */ 221 void Flush(void); 222 223 private: 224 void GetAllPropertiesMethodHandler(DBusRequest &aRequest); 225 void GetPropertyMethodHandler(DBusRequest &aRequest); 226 void SetPropertyMethodHandler(DBusRequest &aRequest); 227 228 static DBusHandlerResult sMessageHandler(DBusConnection *aConnection, DBusMessage *aMessage, void *aData); 229 DBusHandlerResult MessageHandler(DBusConnection *aConnection, DBusMessage *aMessage); 230 231 UniqueDBusMessage NewSignalMessage(const std::string &aInterfaceName, const std::string &aSignalName); 232 233 std::unordered_map<std::string, MethodHandlerType> mMethodHandlers; 234 std::unordered_map<std::string, std::unordered_map<std::string, PropertyHandlerType>> mGetPropertyHandlers; 235 std::unordered_map<std::string, PropertyHandlerType> mSetPropertyHandlers; 236 DBusConnection *mConnection; 237 std::string mObjectPath; 238 }; 239 240 } // namespace DBus 241 } // namespace otbr 242 243 #endif // OTBR_DBUS_DBUS_SERVER_HPP_ 244