xref: /aosp_15_r20/external/ot-br-posix/src/dbus/server/dbus_request.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
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