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