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