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-req-itf.h>
26 #include <afb/afb-service-itf.h>
28 #include "afb-session.h"
29 #include "afb-context.h"
31 #include "afb-msg-json.h"
35 #include "afb-apiset.h"
40 * Structure for recording service
44 /* session of the service */
45 struct afb_session *session;
47 /* the apiset for the service */
48 struct afb_apiset *apiset;
50 /* event listener of the service or NULL */
51 struct afb_evt_listener *listener;
53 /* on event callback for the service */
55 void (*on_event_v1)(const char *event, struct json_object *object);
56 void (*on_event_v2)(struct afb_service service, const char *event, struct json_object *object);
59 /* the daemon interface */
60 struct afb_ditf *ditf;
64 * Structure for requests initiated by the service
71 void (*callback)(void*, int, struct json_object*);
75 /* functions for services */
76 static void svc_on_event_v1(void *closure, const char *event, int eventid, struct json_object *object);
77 static void svc_on_event_v2(void *closure, const char *event, int eventid, struct json_object *object);
78 static void svc_call(void *closure, const char *api, const char *verb, struct json_object *args,
79 void (*callback)(void*, int, struct json_object*), void *cbclosure);
81 /* the interface for services */
82 static const struct afb_service_itf service_itf = {
86 /* the interface for events */
87 static const struct afb_evt_itf evt_itf_v1 = {
88 .broadcast = svc_on_event_v1,
89 .push = svc_on_event_v1
91 static const struct afb_evt_itf evt_itf_v2 = {
92 .broadcast = svc_on_event_v2,
93 .push = svc_on_event_v2
96 /* functions for requests of services */
97 static void svcreq_destroy(struct afb_xreq *xreq);
98 static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj);
100 /* interface for requests of services */
101 const struct afb_xreq_query_itf afb_svc_xreq_itf = {
102 .unref = svcreq_destroy,
103 .reply = svcreq_reply
106 /* the common session for services sharing their session */
107 static struct afb_session *common_session;
109 static inline struct afb_service to_afb_service_v1(struct afb_svc *svc)
111 return (struct afb_service){ .itf = &service_itf, .closure = svc };
114 static inline struct afb_service to_afb_service_v2(struct afb_svc *svc)
116 return (struct afb_service){ .itf = &service_itf, .closure = svc };
122 static void svc_free(struct afb_svc *svc)
124 if (svc->listener != NULL)
125 afb_evt_listener_unref(svc->listener);
127 afb_session_unref(svc->session);
128 afb_apiset_unref(svc->apiset);
133 * Allocates a new service
135 static struct afb_svc *afb_svc_alloc(
136 struct afb_apiset *apiset,
142 /* allocates the svc handler */
143 svc = calloc(1, sizeof * svc);
149 /* instanciate the apiset */
150 svc->apiset = afb_apiset_addref(apiset);
152 /* instanciate the session */
154 /* session shared with other svcs */
155 if (common_session == NULL) {
156 common_session = afb_session_create (NULL, 0);
157 if (common_session == NULL)
160 svc->session = afb_session_addref(common_session);
162 /* session dedicated to the svc */
163 svc->session = afb_session_create (NULL, 0);
164 if (svc->session == NULL)
176 * Creates a new service
178 struct afb_svc *afb_svc_create_v1(
179 struct afb_apiset *apiset,
181 int (*start)(struct afb_service service),
182 void (*on_event)(const char *event, struct json_object *object)
188 /* allocates the svc handler */
189 svc = afb_svc_alloc(apiset, share_session);
193 /* initialises the listener if needed */
195 svc->on_event_v1 = on_event;
196 svc->listener = afb_evt_listener_create(&evt_itf_v1, svc);
197 if (svc->listener == NULL)
201 /* initialises the svc now */
202 rc = start(to_afb_service_v1(svc));
214 * Creates a new service
216 struct afb_svc *afb_svc_create_v2(
217 struct afb_apiset *apiset,
219 int (*start)(struct afb_service service),
220 void (*on_event)(struct afb_service service, const char *event, struct json_object *object),
221 struct afb_ditf *ditf
227 /* allocates the svc handler */
228 svc = afb_svc_alloc(apiset, share_session);
233 /* initialises the listener if needed */
235 svc->on_event_v2 = on_event;
236 svc->listener = afb_evt_listener_create(&evt_itf_v2, svc);
237 if (svc->listener == NULL)
241 /* initialises the svc now */
242 rc = start(to_afb_service_v2(svc));
254 * Propagates the event to the service
256 static void svc_on_event_v1(void *closure, const char *event, int eventid, struct json_object *object)
258 struct afb_svc *svc = closure;
259 svc->on_event_v1(event, object);
260 json_object_put(object);
264 * Propagates the event to the service
266 static void svc_on_event_v2(void *closure, const char *event, int eventid, struct json_object *object)
268 struct afb_svc *svc = closure;
269 svc->on_event_v2(to_afb_service_v2(svc), event, object);
270 json_object_put(object);
274 * Initiates a call for the service
276 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)
278 struct afb_svc *svc = closure;
279 struct svc_req *svcreq;
281 /* allocates the request */
282 svcreq = calloc(1, sizeof *svcreq);
283 if (svcreq == NULL) {
284 ERROR("out of memory");
285 json_object_put(args);
286 callback(cbclosure, 1, afb_msg_json_internal_error());
290 /* initialises the request */
291 afb_xreq_init(&svcreq->xreq, &afb_svc_xreq_itf);
292 afb_context_init(&svcreq->xreq.context, svc->session, NULL);
293 svcreq->xreq.context.validated = 1;
294 svcreq->xreq.cred = afb_cred_current();
295 svcreq->xreq.api = api;
296 svcreq->xreq.verb = verb;
297 svcreq->xreq.listener = svc->listener;
298 svcreq->xreq.json = args;
299 svcreq->callback = callback;
300 svcreq->closure = cbclosure;
302 /* terminates and frees ressources if needed */
303 afb_xreq_process(&svcreq->xreq, svc->apiset);
306 static void svcreq_destroy(struct afb_xreq *xreq)
308 struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
309 afb_context_disconnect(&svcreq->xreq.context);
310 json_object_put(svcreq->xreq.json);
311 afb_cred_unref(svcreq->xreq.cred);
315 static void svcreq_reply(struct afb_xreq *xreq, int iserror, json_object *obj)
317 struct svc_req *svcreq = CONTAINER_OF_XREQ(struct svc_req, xreq);
318 svcreq->callback(svcreq->closure, iserror, obj);
319 json_object_put(obj);