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