4 * Copyright (C) 2018 "IoT.bzh"
5 * Author Loïc Collignon <loic.collignon@iot.bzh>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 #include <afb/afb-binding.h>
29 * @brief Create a new API.
30 * @tparam TApi The Api's concrete class to create an instance from.
31 * @param[in] handle Parent API.
32 * @param[in] name API's name.
33 * @param[in] info API's description.
34 * @param[in] noconcurrency Zero for a reentrant API, non-zero otherwise.
35 * @return The created API.
37 template <typename TApi>
38 TApi* new_api(afb_api_t handle, const std::string& name, const std::string& info = "", int noconcurrency = 1)
40 TApi* api = new TApi();
44 info == "" ? nullptr : info.c_str(),
46 TApi::Traits::preinit,
53 * @brief Default Api's traits implementation.
54 * @tparam TApi The Api's concrete class.
56 template <typename TApi>
60 * @brief TApi's method pointer.
62 using TVerbCallback = void(TApi::*)(req);
65 * @brief TApi's const method pointer.
67 using TVerbCallbackConst = void(TApi::*)(req) const;
70 * @brief Pre-init callback for an api created using @c afb::api::new_api.
71 * @param[in] closure Pointer to the API object.
72 * @param[in] handle Handle of the API.
73 * @return Zero on success, non-zero otherwise.
75 static int preinit(void* closure, afb_api_t handle)
77 assert(closure != nullptr);
78 assert(handle != nullptr);
80 afb_api_set_userdata(handle, closure);
82 TApi* api = reinterpret_cast<TApi*>(closure);
84 if (afb_api_on_init(handle, TApi::Traits::init))
86 AFB_API_ERROR(handle, "Failed to register init handler callback.");
90 if (afb_api_on_event(handle, TApi::Traits::event))
92 AFB_API_ERROR(handle, "Failed to register event handler callback.");
96 api->handle_ = handle;
97 return api->preinit(handle);
101 * @brief Init callback for an api created using @c afb::api::new_api.
102 * @param[in] handle Handle to the API to initialize.
103 * @return Zero on success, non-zero otherwise.
105 static int init(afb_api_t handle)
107 assert(handle != nullptr);
109 void* userdata = afb_api_get_userdata(handle);
110 assert(userdata != nullptr);
112 TApi* api = reinterpret_cast<TApi*>(userdata);
117 * @brief Event callback for an api created using @c afb::api::new_api.
118 * @param[in] handle Handle to the API that is receiving an event.
119 * @param[in] event The event's name.
120 * @param[in] object The event's json argument.
122 static void event(afb_api_t handle, const char* event, json_object* object)
124 assert(handle != nullptr);
126 void* userdata = afb_api_get_userdata(handle);
127 assert(userdata != nullptr);
129 TApi* api = reinterpret_cast<TApi*>(userdata);
130 api->event(event, object);
134 * @brief Verb callback for a verb added using @c afb::api::add_verb.
135 * @tparam callback TApi's method to call
136 * @param[in] r Request to handle.
138 template <TVerbCallback callback>
139 static void verb(afb_req_t r)
141 assert(r != nullptr);
143 afb_api_t handle = afb_req_get_api(r);
146 void* userdata = afb_api_get_userdata(handle);
149 TApi* api = reinterpret_cast<TApi*>(userdata);
150 (api->*callback)(afb::req(r));
154 afb_req_fail(r, "Failed to get the API object!", nullptr);
159 afb_req_fail(r, "Failed to get the corresponding API from the query!", nullptr);
164 * @brief Verb callback for a verb added using @c afb::api::add_verb.
165 * @tparam callback TApi's const method to call.
166 * @param[in] req Request to handle.
168 template <TVerbCallbackConst callback>
169 static void verb(afb_req_t r)
171 assert(r != nullptr);
173 afb_api_t handle = afb_req_get_api(r);
176 void* userdata = afb_api_get_userdata(handle);
179 TApi* api = reinterpret_cast<TApi*>(userdata);
180 (api->*callback)(afb::req(r));
184 afb_req_fail(r, "Failed to get the API object!", nullptr);
189 afb_req_fail(r, "Failed to get the corresponding API from the query!", nullptr);
195 * @brief Base class for API implementation.
196 * @tparam TApi The Api's concrete class.
197 * @tparam TTraits The Api's static callback implementation.
201 typename TTraits = ApiTraits<TApi>
208 using Traits = TTraits;
212 base_api_t(const base_api_t&) = delete;
213 base_api_t& operator=(const base_api_t&) = delete;
219 * @brief Default constructor.
221 explicit base_api_t() = default;
224 * @brief Move constructor.
226 explicit base_api_t(base_api_t&&) = default;
229 * @brief Add a verb to an API.
230 * @param[in] api API on which the verb should be added.
231 * @param[in] verb Verb's name.
232 * @param[in] info Verb's description.
233 * @param[in] auth Verb's permissions required.
234 * @param[in] session Verb's session handling.
235 * @param[in] glob is the verb glob name.
236 * @return Zero if success, non-zero otherwise.
238 template <typename TTraits::TVerbCallback Callback>
239 int add_verb(const std::string& verb, const std::string& info, void* vcbdata = nullptr, const struct afb_auth* auth = nullptr, uint32_t session = AFB_SESSION_NONE_X2, int glob = 0)
241 return afb_api_add_verb(
244 info == "" ? nullptr : info.c_str(),
245 TTraits::template verb<Callback>,
254 * @brief Add a verb to an API.
255 * @param[in] api API on which the verb should be added.
256 * @param[in] verb Verb's name.
257 * @param[in] info Verb's description.
258 * @param[in] auth Verb's permissions required.
259 * @param[in] session Verb's session handling.
260 * @param[in] glob is the verb glob name.
261 * @return Zero if success, non-zero otherwise.
263 template <typename TTraits::TVerbCallbackConst Callback>
264 int add_verb(const std::string& verb, const std::string& info, void* vcbdata = nullptr, const struct afb_auth* auth = nullptr, uint32_t session = AFB_SESSION_NONE_X2, int glob = 0)
266 return afb_api_add_verb(
269 info == "" ? nullptr : info.c_str(),
270 TTraits::template verb<Callback>,
280 * @brief Move assignation operator.
282 base_api_t& operator=(base_api_t&&) = default;
285 * @brief Get the API's handle.
286 * @return The API's handle.
288 afb_api_t handle() const { return handle_; }
291 * @brief Implicit conversion to C handle.
292 * @return The API's handle.
294 operator afb_api_t() const { return handle_; }
299 virtual ~base_api_t()
301 if (handle_ && afb_api_delete_api(handle_))
302 AFB_API_ERROR(handle_, "Failed to delete API.");
306 * @brief Called by the binder during the API's pre-init phase.
307 * @param[in] handle Handle representing the API on the binder's side.
308 * @return Zero if success, non-zero otherwise.
310 virtual int preinit(afb_api_t handle) { return 0; }
313 * @brief Called by the binder during the API's init phase.
314 * @return Zero on success, non-zero otherwise.
316 virtual int init() { return 0; }
319 * @brief Called by the binder when an event is received for this API.
320 * @param[in] name Event's name.
321 * @param[in] arg Event's argument.
323 virtual void event(const std::string& name, json_object* arg) { }