2 * Copyright (C) 2016, 2017 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
23 #include <json-c/json.h>
25 #include <afb/afb-binding-v1.h>
26 #include <afb/afb-binding-v2.h>
28 #include "afb-session.h"
29 #include "afb-context.h"
31 #include "afb-msg-json.h"
35 #include "afb-apiset.h"
39 * Structure for recording service
43 /* session of the service */
44 struct afb_session *session;
46 /* the apiset for the service */
47 struct afb_apiset *apiset;
49 /* event listener of the service or NULL */
50 struct afb_evt_listener *listener;
52 /* on event callback for the service */
53 void (*on_event)(const char *event, struct json_object *object);
55 struct afb_binding_data_v2 *v2;
59 * Structure for requests initiated by the service
66 void (*callback)(void*, int, struct json_object*);
70 /* functions for services */
71 static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object);
72 static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args,
73 void (*callback)(void*, int, struct json_object*), void *cbclosure);
75 /* the interface for services */
76 static const struct afb_service_itf service_itf = {
80 /* the interface for events */
81 static const struct afb_evt_itf evt_itf = {
82 .broadcast = svc_on_event,
86 /* functions for requests of services */
87 static void svcreq_destroy(struct afb_xreq *xreq);
88 static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj);
90 /* interface for requests of services */
91 const struct afb_xreq_query_itf afb_svc_xreq_itf = {
92 .unref = svcreq_destroy,
96 /* the common session for services sharing their session */
97 static struct afb_session *common_session;
99 static inline struct afb_service to_afb_service_v1(struct afb_svc *svc)
101 return (struct afb_service){ .itf = &service_itf, .closure = svc };
104 static inline struct afb_service to_afb_service_v2(struct afb_svc *svc)
106 return (struct afb_service){ .itf = &service_itf, .closure = svc };
112 static void svc_free(struct afb_svc *svc)
114 if (svc->listener != NULL)
115 afb_evt_listener_unref(svc->listener);
117 afb_session_unref(svc->session);
118 afb_apiset_unref(svc->apiset);
123 * Allocates a new service
125 static struct afb_svc *afb_svc_alloc(
126 struct afb_apiset *apiset,
132 /* allocates the svc handler */
133 svc = calloc(1, sizeof * svc);
139 /* instanciate the apiset */
140 svc->apiset = afb_apiset_addref(apiset);
142 /* instanciate the session */
144 /* session shared with other svcs */
145 if (common_session == NULL) {
146 common_session = afb_session_create (NULL, 0);
147 if (common_session == NULL)
150 svc->session = afb_session_addref(common_session);
152 /* session dedicated to the svc */
153 svc->session = afb_session_create (NULL, 0);
154 if (svc->session == NULL)
166 * Creates a new service
168 struct afb_svc *afb_svc_create_v1(
169 struct afb_apiset *apiset,
171 int (*start)(struct afb_service service),
172 void (*on_event)(const char *event, struct json_object *object)
178 /* allocates the svc handler */
179 svc = afb_svc_alloc(apiset, share_session);
183 /* initialises the listener if needed */
185 svc->on_event = on_event;
186 svc->listener = afb_evt_listener_create(&evt_itf, svc);
187 if (svc->listener == NULL)
191 /* initialises the svc now */
192 rc = start(to_afb_service_v1(svc));
204 * Creates a new service
206 struct afb_svc *afb_svc_create_v2(
207 struct afb_apiset *apiset,
210 void (*on_event)(const char *event, struct json_object *object),
211 struct afb_binding_data_v2 *data
217 /* allocates the svc handler */
218 svc = afb_svc_alloc(apiset, share_session);
222 data->service = to_afb_service_v2(svc);
224 /* initialises the listener if needed */
226 svc->on_event = on_event;
227 svc->listener = afb_evt_listener_create(&evt_itf, svc);
228 if (svc->listener == NULL)
232 /* starts the svc if needed */
247 * Propagates the event to the service
249 static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object)
251 struct afb_svc *svc = closure;
252 svc->on_event(event, object);
253 json_object_put(object);
257 * Initiates a call for the service
259 static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure)
261 struct afb_svc *svc = closure;
262 struct svc_req *svcreq;
264 /* allocates the request */
265 svcreq = calloc(1, sizeof *svcreq);
266 if (svcreq == NULL) {
267 ERROR("out of memory");
268 json_object_put(args);
269 callback(cbclosure, 1, afb_msg_json_internal_error());
273 /* initialises the request */
274 afb_xreq_init(&svcreq->xreq, &afb_svc_xreq_itf);
275 afb_context_init(&svcreq->xreq.context, svc->session, NULL);
276 svcreq->xreq.context.validated = 1;
277 svcreq->xreq.cred = afb_cred_current();
278 svcreq->xreq.api = api;
279 svcreq->xreq.verb = verb;
280 svcreq->xreq.listener = svc->listener;
281 svcreq->xreq.json = args;
282 svcreq->callback = callback;
283 svcreq->closure = cbclosure;
285 /* terminates and frees ressources if needed */
286 afb_xreq_process(&svcreq->xreq, svc->apiset);
289 static void svcreq_destroy(struct afb_xreq *xreq)
291 struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
292 afb_context_disconnect(&svcreq->xreq.context);
293 json_object_put(svcreq->xreq.json);
294 afb_cred_unref(svcreq->xreq.cred);
298 static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj)
300 struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
301 svcreq->callback(svcreq->closure, iserror, obj);
302 json_object_put(obj);