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.
20 #include <afb/c++/binding-wrap.hpp>
27 * @brief Create a new API.
28 * @tparam TApi The Api's concrete class to create an instance from.
29 * @param[in] handle Parent API.
30 * @param[in] name API's name.
31 * @param[in] info API's description.
32 * @param[in] noconcurrency Zero for a reentrant API, non-zero otherwise.
33 * @return The created API.
35 template <typename TApi>
36 TApi* new_api(afb_api_t handle, const std::string& name, const std::string& info = "", int noconcurrency = 1)
38 TApi* api = new TApi();
42 info == "" ? nullptr : info.c_str(),
44 TApi::Traits::preinit,
51 * @brief Default Api's traits implementation.
52 * @tparam TApi The Api's concrete class.
54 template <typename TApi>
58 * @brief TApi's method pointer.
60 using TVerbCallback = void(TApi::*)(req);
63 * @brief TApi's const method pointer.
65 using TVerbCallbackConst = void(TApi::*)(req) const;
68 * @brief Pre-init callback for an api created using @c afb::api::new_api.
69 * @param[in] closure Pointer to the API object.
70 * @param[in] handle Handle of the API.
71 * @return Zero on success, non-zero otherwise.
73 static int preinit(void* closure, afb_api_t handle)
75 assert(closure != nullptr);
76 assert(handle != nullptr);
78 afb_api_set_userdata(handle, closure);
80 TApi* api = reinterpret_cast<TApi*>(closure);
82 if (afb_api_on_init(handle, TApi::Traits::init))
84 AFB_API_ERROR(handle, "Failed to register init handler callback.");
88 if (afb_api_on_event(handle, TApi::Traits::event))
90 AFB_API_ERROR(handle, "Failed to register event handler callback.");
95 return api->preinit(handle);
99 * @brief Init callback for an api created using @c afb::api::new_api.
100 * @param[in] handle Handle to the API to initialize.
101 * @return Zero on success, non-zero otherwise.
103 static int init(afb_api_t handle)
105 assert(handle != nullptr);
107 void* userdata = afb_api_get_userdata(handle);
108 assert(userdata != nullptr);
110 TApi* api = reinterpret_cast<TApi*>(userdata);
115 * @brief Event callback for an api created using @c afb::api::new_api.
116 * @param[in] handle Handle to the API that is receiving an event.
117 * @param[in] event The event's name.
118 * @param[in] object The event's json argument.
120 static void event(afb_api_t handle, const char* event, json_object* object)
122 assert(handle != nullptr);
124 void* userdata = afb_api_get_userdata(handle);
125 assert(userdata != nullptr);
127 TApi* api = reinterpret_cast<TApi*>(userdata);
128 api->event(event, object);
132 * @brief Verb callback for a verb added using @c afb::api::add_verb.
133 * @tparam callback TApi's method to call
134 * @param[in] r Request to handle.
136 template <TVerbCallback callback>
137 static void verb(afb_req_t r)
139 assert(r != nullptr);
141 afb_api_t handle = afb_req_get_api(r);
144 void* userdata = afb_api_get_userdata(handle);
147 TApi* api = reinterpret_cast<TApi*>(userdata);
148 (api->*callback)(afb::req(r));
152 afb_req_fail(r, "Failed to get the API object!", nullptr);
157 afb_req_fail(r, "Failed to get the corresponding API from the query!", nullptr);
162 * @brief Verb callback for a verb added using @c afb::api::add_verb.
163 * @tparam callback TApi's const method to call.
164 * @param[in] req Request to handle.
166 template <TVerbCallbackConst callback>
167 static void verb(afb_req_t r)
169 assert(r != nullptr);
171 afb_api_t handle = afb_req_get_api(r);
174 void* userdata = afb_api_get_userdata(handle);
177 TApi* api = reinterpret_cast<TApi*>(userdata);
178 (api->*callback)(afb::req(r));
182 afb_req_fail(r, "Failed to get the API object!", nullptr);
187 afb_req_fail(r, "Failed to get the corresponding API from the query!", nullptr);
193 * @brief Base class for API implementation.
194 * @tparam TApi The Api's concrete class.
195 * @tparam TTraits The Api's static callback implementation.
199 typename TTraits = ApiTraits<TApi>
207 using Traits = TTraits;
211 base_api_t(const base_api_t&) = delete;
212 base_api_t& operator=(const base_api_t&) = delete;
216 * @brief Default constructor.
218 explicit base_api_t() = default;
221 * @brief Move constructor.
223 explicit base_api_t(base_api_t&&) = default;
226 * @brief Add a verb to an API.
227 * @param[in] api API on which the verb should be added.
228 * @param[in] verb Verb's name.
229 * @param[in] info Verb's description.
230 * @param[in] auth Verb's permissions required.
231 * @param[in] session Verb's session handling.
232 * @param[in] glob is the verb glob name.
233 * @return Zero if success, non-zero otherwise.
235 template <typename TTraits::TVerbCallback Callback>
236 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)
238 return afb_api_add_verb(
241 info == "" ? nullptr : info.c_str(),
242 TTraits::template verb<Callback>,
251 * @brief Add a verb to an API.
252 * @param[in] api API on which the verb should be added.
253 * @param[in] verb Verb's name.
254 * @param[in] info Verb's description.
255 * @param[in] auth Verb's permissions required.
256 * @param[in] session Verb's session handling.
257 * @param[in] glob is the verb glob name.
258 * @return Zero if success, non-zero otherwise.
260 template <typename TTraits::TVerbCallbackConst Callback>
261 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)
263 return afb_api_add_verb(
266 info == "" ? nullptr : info.c_str(),
267 TTraits::template verb<Callback>,
277 * @brief Move assignation operator.
279 base_api_t& operator=(base_api_t&&) = default;
282 * @brief Get the API's handle.
283 * @return The API's handle.
285 afb_api_t handle() const { return api_; }
288 * @brief Implicit conversion to C handle.
289 * @return The API's handle.
291 operator afb_api_t() const { return api_; }
296 virtual ~base_api_t()
298 if (api_ && afb_api_delete_api(api_))
299 AFB_API_ERROR(api_, "Failed to delete API.");
303 * @brief Called by the binder during the API's pre-init phase.
304 * @param[in] handle Handle representing the API on the binder's side.
305 * @return Zero if success, non-zero otherwise.
307 virtual int preinit(afb_api_t handle) { return 0; }
310 * @brief Called by the binder during the API's init phase.
311 * @return Zero on success, non-zero otherwise.
313 virtual int init() { return 0; }
316 * @brief Called by the binder when an event is received for this API.
317 * @param[in] name Event's name.
318 * @param[in] arg Event's argument.
320 virtual void event(const std::string& name, json_object* arg) { }