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.
22 #include <json-c/json.h>
24 #include <afb/afb-req-itf.h>
25 #include <afb/afb-service-itf.h>
27 #include "afb-session.h"
28 #include "afb-context.h"
30 #include "afb-msg-json.h"
34 #include "afb-apiset.h"
38 * Structure for recording service
42 /* session of the service */
43 struct afb_session *session;
45 /* the apiset for the service */
46 struct afb_apiset *apiset;
48 /* event listener of the service or NULL */
49 struct afb_evt_listener *listener;
51 /* on event callback for the service */
52 void (*on_event)(const char *event, struct json_object *object);
56 * Structure for requests initiated by the service
63 void (*callback)(void*, int, struct json_object*);
67 /* functions for services */
68 static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object);
69 static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args,
70 void (*callback)(void*, int, struct json_object*), void *cbclosure);
72 /* the interface for services */
73 static const struct afb_service_itf service_itf = {
77 /* the interface for events */
78 static const struct afb_evt_itf evt_itf = {
79 .broadcast = svc_on_event,
83 /* functions for requests of services */
84 static void svcreq_destroy(struct afb_xreq *xreq);
85 static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj);
87 /* interface for requests of services */
88 const struct afb_xreq_query_itf afb_svc_xreq_itf = {
89 .unref = svcreq_destroy,
93 /* the common session for services sharing their session */
94 static struct afb_session *common_session;
97 * Allocates a new service
99 static struct afb_svc *afb_svc_alloc(
100 struct afb_apiset *apiset,
102 void (*on_event)(const char *event, struct json_object *object)
107 /* allocates the svc handler */
108 svc = malloc(sizeof * svc);
112 /* instanciate the apiset */
113 svc->apiset = afb_apiset_addref(apiset);
115 /* instanciate the session */
117 /* session shared with other svcs */
118 if (common_session == NULL) {
119 common_session = afb_session_create (NULL, 0);
120 if (common_session == NULL)
123 svc->session = afb_session_addref(common_session);
125 /* session dedicated to the svc */
126 svc->session = afb_session_create (NULL, 0);
127 if (svc->session == NULL)
131 /* initialises the listener if needed */
132 svc->on_event = on_event;
133 if (on_event == NULL)
134 svc->listener = NULL;
136 svc->listener = afb_evt_listener_create(&evt_itf, svc);
137 if (svc->listener == NULL)
144 afb_session_unref(svc->session);
146 afb_apiset_unref(svc->apiset);
153 * Creates a new service
155 struct afb_svc *afb_svc_create(
156 struct afb_apiset *apiset,
158 int (*init)(struct afb_service service),
159 void (*on_event)(const char *event, struct json_object *object)
165 /* allocates the svc handler */
166 svc = afb_svc_alloc(apiset, share_session, on_event);
170 /* initialises the svc now */
171 rc = init((struct afb_service){ .itf = &service_itf, .closure = svc });
178 if (svc->listener != NULL)
179 afb_evt_listener_unref(svc->listener);
180 afb_session_unref(svc->session);
181 afb_apiset_unref(svc->apiset);
188 * Creates a new service
190 struct afb_svc *afb_svc_create_v2(
191 struct afb_apiset *apiset,
193 void (*on_event)(const char *event, struct json_object *object),
194 int (*start)(const struct afb_binding_interface *interface, struct afb_service service),
195 const struct afb_binding_interface *interface
201 /* allocates the svc handler */
202 svc = afb_svc_alloc(apiset, share_session, on_event);
206 /* initialises the svc now */
207 rc = start(interface, (struct afb_service){ .itf = &service_itf, .closure = svc });
214 if (svc->listener != NULL)
215 afb_evt_listener_unref(svc->listener);
216 afb_session_unref(svc->session);
217 afb_apiset_unref(svc->apiset);
224 * Propagates the event to the service
226 static void svc_on_event(void *closure, const char *event, int eventid, struct json_object *object)
228 struct afb_svc *svc = closure;
229 svc->on_event(event, object);
230 json_object_put(object);
234 * Initiates a call for the service
236 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)
238 struct afb_svc *svc = closure;
239 struct svc_req *svcreq;
241 /* allocates the request */
242 svcreq = calloc(1, sizeof *svcreq);
243 if (svcreq == NULL) {
244 ERROR("out of memory");
245 json_object_put(args);
246 callback(cbclosure, 1, afb_msg_json_internal_error());
250 /* initialises the request */
251 afb_xreq_init(&svcreq->xreq, &afb_svc_xreq_itf);
252 afb_context_init(&svcreq->xreq.context, svc->session, NULL);
253 svcreq->xreq.context.validated = 1;
254 svcreq->xreq.cred = afb_cred_current();
255 svcreq->xreq.api = api;
256 svcreq->xreq.verb = verb;
257 svcreq->xreq.listener = svc->listener;
258 svcreq->xreq.json = args;
259 svcreq->callback = callback;
260 svcreq->closure = cbclosure;
262 /* terminates and frees ressources if needed */
263 afb_xreq_process(&svcreq->xreq, svc->apiset);
266 static void svcreq_destroy(struct afb_xreq *xreq)
268 struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
269 afb_context_disconnect(&svcreq->xreq.context);
270 json_object_put(svcreq->xreq.json);
271 afb_cred_unref(svcreq->xreq.cred);
275 static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj)
277 struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
278 svcreq->callback(svcreq->closure, iserror, obj);
279 json_object_put(obj);