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 request. 32 */ 33 34 #ifndef DBUS_SERVER_DBUS_REQUEST_HPP_ 35 #define DBUS_SERVER_DBUS_REQUEST_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 "common/code_utils.hpp" 44 #include "common/logging.hpp" 45 46 #include "dbus/common/dbus_message_dump.hpp" 47 #include "dbus/common/dbus_message_helper.hpp" 48 #include "dbus/common/dbus_resources.hpp" 49 #include "dbus/server/error_helper.hpp" 50 51 namespace otbr { 52 namespace DBus { 53 54 /** 55 * This class represents a incoming call for a d-bus method. 56 */ 57 class DBusRequest 58 { 59 public: 60 /** 61 * The constructor of dbus request. 62 * 63 * @param[in] aConnection The dbus connection. 64 * @param[in] aMessage The incoming dbus message. 65 */ DBusRequest(DBusConnection * aConnection,DBusMessage * aMessage)66 DBusRequest(DBusConnection *aConnection, DBusMessage *aMessage) 67 : mConnection(aConnection) 68 , mMessage(aMessage) 69 { 70 dbus_message_ref(aMessage); 71 dbus_connection_ref(aConnection); 72 } 73 74 /** 75 * The copy constructor of dbus request. 76 * 77 * @param[in] aOther The object to be copied from. 78 */ DBusRequest(const DBusRequest & aOther)79 DBusRequest(const DBusRequest &aOther) 80 : mConnection(nullptr) 81 , mMessage(nullptr) 82 { 83 CopyFrom(aOther); 84 } 85 86 /** 87 * The assignment operator of dbus request. 88 * 89 * @param[in] aOther The object to be copied from. 90 */ operator =(const DBusRequest & aOther)91 DBusRequest &operator=(const DBusRequest &aOther) 92 { 93 CopyFrom(aOther); 94 return *this; 95 } 96 97 /** 98 * This method returns the message sent to call the d-bus method. 99 * 100 * @returns The dbus message. 101 */ GetMessage(void)102 DBusMessage *GetMessage(void) { return mMessage; } 103 104 /** 105 * This method returns underlying d-bus connection. 106 * 107 * @returns The dbus connection. 108 */ GetConnection(void)109 DBusConnection *GetConnection(void) { return mConnection; } 110 111 /** 112 * This method replies to the d-bus method call. 113 * 114 * @param[in] aReply The tuple to be sent. 115 */ Reply(const std::tuple<Args...> & aReply)116 template <typename... Args> void Reply(const std::tuple<Args...> &aReply) 117 { 118 UniqueDBusMessage reply{dbus_message_new_method_return(mMessage)}; 119 120 VerifyOrExit(reply != nullptr); 121 VerifyOrExit(otbr::DBus::TupleToDBusMessage(*reply, aReply) == OTBR_ERROR_NONE); 122 123 if (otbrLogGetLevel() >= OTBR_LOG_DEBUG) 124 { 125 otbrLogDebug("Replied to %s.%s :", dbus_message_get_interface(mMessage), dbus_message_get_member(mMessage)); 126 DumpDBusMessage(*reply); 127 } 128 dbus_connection_send(mConnection, reply.get(), nullptr); 129 130 exit: 131 return; 132 } 133 134 /** 135 * This method replies an otError to the d-bus method call. 136 * 137 * @param[in] aError The error to be sent. 138 * @param[in] aResult The return value of the method call, if any. 139 */ 140 template <typename ResultType = int> ReplyOtResult(otError aError,Optional<ResultType> aResult=Optional<ResultType> ())141 void ReplyOtResult(otError aError, Optional<ResultType> aResult = Optional<ResultType>()) 142 { 143 UniqueDBusMessage reply{nullptr}; 144 145 if (aError == OT_ERROR_NONE) 146 { 147 otbrLogInfo("Replied to %s.%s with result %s", dbus_message_get_interface(mMessage), 148 dbus_message_get_member(mMessage), ConvertToDBusErrorName(aError)); 149 } 150 else 151 { 152 otbrLogErr("Replied to %s.%s with result %s", dbus_message_get_interface(mMessage), 153 dbus_message_get_member(mMessage), ConvertToDBusErrorName(aError)); 154 } 155 156 if (aError == OT_ERROR_NONE) 157 { 158 reply = UniqueDBusMessage(dbus_message_new_method_return(mMessage)); 159 } 160 else 161 { 162 reply = UniqueDBusMessage(dbus_message_new_error(mMessage, ConvertToDBusErrorName(aError), nullptr)); 163 } 164 VerifyOrDie(reply != nullptr, "Failed to allocate message"); 165 166 if (aResult.HasValue()) 167 { 168 DBusMessageIter replyIter; 169 otbrError error; 170 171 dbus_message_iter_init_append(reply.get(), &replyIter); 172 error = DBusMessageEncode(&replyIter, *aResult); 173 VerifyOrDie(error == OTBR_ERROR_NONE, "Failed to encode result"); 174 } 175 176 dbus_connection_send(mConnection, reply.get(), nullptr); 177 } 178 179 /** 180 * The destructor of DBusRequest 181 */ ~DBusRequest(void)182 ~DBusRequest(void) 183 { 184 if (mConnection) 185 { 186 dbus_connection_unref(mConnection); 187 } 188 if (mMessage) 189 { 190 dbus_message_unref(mMessage); 191 } 192 } 193 194 private: CopyFrom(const DBusRequest & aOther)195 void CopyFrom(const DBusRequest &aOther) 196 { 197 if (mMessage) 198 { 199 dbus_message_unref(mMessage); 200 } 201 if (mConnection) 202 { 203 dbus_connection_unref(mConnection); 204 } 205 mConnection = aOther.mConnection; 206 mMessage = aOther.mMessage; 207 dbus_message_ref(mMessage); 208 dbus_connection_ref(mConnection); 209 } 210 211 DBusConnection *mConnection; 212 DBusMessage *mMessage; 213 }; 214 215 } // namespace DBus 216 } // namespace otbr 217 218 #endif // DBUS_SERVER_DBUS_REQUEST_HPP_ 219