Update date of copyright notices
[src/app-framework-binder.git] / src / afb-export.c
1 /*
2  * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
3  * Author: José Bollo <jose.bollo@iot.bzh>
4  *
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
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 #define _GNU_SOURCE
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23
24 #include <json-c/json.h>
25
26 #define AFB_BINDING_VERSION 0
27 #include <afb/afb-binding.h>
28
29 #include "afb-api.h"
30 #include "afb-apiset.h"
31 #include "afb-api-dyn.h"
32 #include "afb-common.h"
33 #include "afb-systemd.h"
34 #include "afb-cred.h"
35 #include "afb-evt.h"
36 #include "afb-export.h"
37 #include "afb-hook.h"
38 #include "afb-msg-json.h"
39 #include "afb-session.h"
40 #include "afb-xreq.h"
41 #include "jobs.h"
42 #include "verbose.h"
43
44 /*************************************************************************
45  * internal types and structures
46  ************************************************************************/
47
48 enum afb_api_version
49 {
50         Api_Version_Dyn = 0,
51         Api_Version_1 = 1,
52         Api_Version_2 = 2,
53 };
54
55 enum afb_api_state
56 {
57         Api_State_Pre_Init,
58         Api_State_Init,
59         Api_State_Run
60 };
61
62 struct afb_export
63 {
64         /* keep it first */
65         struct afb_dynapi dynapi;
66
67         /* name of the api */
68         char *apiname;
69
70         /* version of the api */
71         unsigned version: 4;
72
73         /* current state */
74         unsigned state: 4;
75
76         /* hooking flags */
77         int hookditf;
78         int hooksvc;
79
80         /* dynamic api */
81         struct afb_api_dyn *apidyn;
82
83         /* session for service */
84         struct afb_session *session;
85
86         /* apiset for service */
87         struct afb_apiset *apiset;
88
89         /* event listener for service or NULL */
90         struct afb_evt_listener *listener;
91
92         /* start function */
93         union {
94                 int (*v1)(struct afb_service);
95                 int (*v2)();
96                 int (*vdyn)(struct afb_dynapi *dynapi);
97         } init;
98
99         /* event handling */
100         union {
101                 void (*v12)(const char *event, struct json_object *object);
102                 void (*vdyn)(struct afb_dynapi *dynapi, const char *event, struct json_object *object);
103         } on_event;
104
105         /* exported data */
106         union {
107                 struct afb_binding_interface_v1 v1;
108                 struct afb_binding_data_v2 *v2;
109         } export;
110 };
111
112 /************************************************************************************************************/
113
114 static inline struct afb_dynapi *to_dynapi(struct afb_export *export)
115 {
116         return (struct afb_dynapi*)export;
117 }
118
119 static inline struct afb_export *from_dynapi(struct afb_dynapi *dynapi)
120 {
121         return (struct afb_export*)dynapi;
122 }
123
124 /*************************************************************************************************************
125  *************************************************************************************************************
126  *************************************************************************************************************
127  *************************************************************************************************************
128                                            F R O M     D I T F
129  *************************************************************************************************************
130  *************************************************************************************************************
131  *************************************************************************************************************
132  *************************************************************************************************************/
133
134 /**********************************************
135 * normal flow
136 **********************************************/
137 static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
138 {
139         char *p;
140         struct afb_export *export = closure;
141
142         if (!fmt || vasprintf(&p, fmt, args) < 0)
143                 vverbose(level, file, line, function, fmt, args);
144         else {
145                 verbose(level, file, line, function, "[API %s] %s", export->apiname, p);
146                 free(p);
147         }
148 }
149
150 static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
151 {
152         vverbose_cb(closure, level, file, line, NULL, fmt, args);
153 }
154
155 static struct afb_eventid *eventid_make_cb(void *closure, const char *name)
156 {
157         struct afb_export *export = closure;
158
159         /* check daemon state */
160         if (export->state == Api_State_Pre_Init) {
161                 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name);
162                 errno = EINVAL;
163                 return NULL;
164         }
165
166         /* create the event */
167         return afb_evt_eventid_create2(export->apiname, name);
168 }
169
170 static struct afb_event event_make_cb(void *closure, const char *name)
171 {
172         struct afb_eventid *eventid = eventid_make_cb(closure, name);
173         return afb_evt_event_from_evtid(afb_evt_eventid_to_evtid(eventid));
174 }
175
176 static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
177 {
178         size_t plen, nlen;
179         char *event;
180         struct afb_export *export = closure;
181
182         /* check daemon state */
183         if (export->state == Api_State_Pre_Init) {
184                 ERROR("[API %s] Bad call to 'afb_daemon_event_broadcast(%s, %s)', must not be in PreInit", export->apiname, name, json_object_to_json_string(object));
185                 errno = EINVAL;
186                 return 0;
187         }
188
189         /* makes the event name */
190         plen = strlen(export->apiname);
191         nlen = strlen(name);
192         event = alloca(nlen + plen + 2);
193         memcpy(event, export->apiname, plen);
194         event[plen] = '/';
195         memcpy(event + plen + 1, name, nlen + 1);
196
197         /* broadcast the event */
198         return afb_evt_broadcast(event, object);
199 }
200
201 static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
202 {
203         return afb_common_rootdir_open_locale(filename, flags, locale);
204 }
205
206 static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
207 {
208         return jobs_queue(group, timeout, callback, argument);
209 }
210
211 static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq)
212 {
213         return afb_xreq_unstore(sreq);
214 }
215
216 static int require_api_cb(void *closure, const char *name, int initialized)
217 {
218         struct afb_export *export = closure;
219         if (export->state != Api_State_Init) {
220                 ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized);
221                 errno = EINVAL;
222                 return -1;
223         }
224         return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
225 }
226
227 static int rename_api_cb(void *closure, const char *name)
228 {
229         struct afb_export *export = closure;
230         if (export->state != Api_State_Pre_Init) {
231                 ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name);
232                 errno = EINVAL;
233                 return -1;
234         }
235         if (!afb_api_is_valid_name(name, 1)) {
236                 ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name);
237                 errno = EINVAL;
238                 return -1;
239         }
240         NOTICE("[API %s] renamed to [API %s]", export->apiname, name);
241         afb_export_rename(export, name);
242         return 0;
243 }
244
245 static int api_new_api_cb(
246                 void *closure,
247                 const char *api,
248                 const char *info,
249                 int noconcurrency,
250                 int (*preinit)(void*, struct afb_dynapi *),
251                 void *preinit_closure)
252 {
253         struct afb_export *export = closure;
254         return afb_api_dyn_add(export->apiset, api, info, noconcurrency, preinit, preinit_closure);
255 }
256
257 /**********************************************
258 * hooked flow
259 **********************************************/
260 static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
261 {
262         struct afb_export *export = closure;
263         va_list ap;
264         va_copy(ap, args);
265         vverbose_cb(closure, level, file, line, function, fmt, args);
266         afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap);
267         va_end(ap);
268 }
269
270 static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
271 {
272         hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
273 }
274
275 static struct afb_eventid *hooked_eventid_make_cb(void *closure, const char *name)
276 {
277         struct afb_export *export = closure;
278         struct afb_eventid *r = eventid_make_cb(closure, name);
279         afb_hook_ditf_event_make(export, name, r);
280         return r;
281 }
282
283 static struct afb_event hooked_event_make_cb(void *closure, const char *name)
284 {
285         struct afb_eventid *eventid = hooked_eventid_make_cb(closure, name);
286         return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
287 }
288
289 static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
290 {
291         int r;
292         struct afb_export *export = closure;
293         json_object_get(object);
294         afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object));
295         r = event_broadcast_cb(closure, name, object);
296         afb_hook_ditf_event_broadcast_after(export, name, object, r);
297         json_object_put(object);
298         return r;
299 }
300
301 static struct sd_event *hooked_get_event_loop(void *closure)
302 {
303         struct afb_export *export = closure;
304         struct sd_event *r = afb_systemd_get_event_loop();
305         return afb_hook_ditf_get_event_loop(export, r);
306 }
307
308 static struct sd_bus *hooked_get_user_bus(void *closure)
309 {
310         struct afb_export *export = closure;
311         struct sd_bus *r = afb_systemd_get_user_bus();
312         return afb_hook_ditf_get_user_bus(export, r);
313 }
314
315 static struct sd_bus *hooked_get_system_bus(void *closure)
316 {
317         struct afb_export *export = closure;
318         struct sd_bus *r = afb_systemd_get_system_bus();
319         return afb_hook_ditf_get_system_bus(export, r);
320 }
321
322 static int hooked_rootdir_get_fd(void *closure)
323 {
324         struct afb_export *export = closure;
325         int r = afb_common_rootdir_get_fd();
326         return afb_hook_ditf_rootdir_get_fd(export, r);
327 }
328
329 static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
330 {
331         struct afb_export *export = closure;
332         int r = rootdir_open_locale_cb(closure, filename, flags, locale);
333         return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r);
334 }
335
336 static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
337 {
338         struct afb_export *export = closure;
339         int r = queue_job_cb(closure, callback, argument, group, timeout);
340         return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r);
341 }
342
343 static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq)
344 {
345         struct afb_export *export = closure;
346         afb_hook_ditf_unstore_req(export, sreq);
347         return unstore_req_cb(closure, sreq);
348 }
349
350 static int hooked_require_api_cb(void *closure, const char *name, int initialized)
351 {
352         int result;
353         struct afb_export *export = closure;
354         afb_hook_ditf_require_api(export, name, initialized);
355         result = require_api_cb(closure, name, initialized);
356         return afb_hook_ditf_require_api_result(export, name, initialized, result);
357 }
358
359 static int hooked_rename_api_cb(void *closure, const char *name)
360 {
361         struct afb_export *export = closure;
362         const char *oldname = export->apiname;
363         int result = rename_api_cb(closure, name);
364         return afb_hook_ditf_rename_api(export, oldname, name, result);
365 }
366
367 static int hooked_api_new_api_cb(
368                 void *closure,
369                 const char *api,
370                 const char *info,
371                 int noconcurrency,
372                 int (*preinit)(void*, struct afb_dynapi *),
373                 void *preinit_closure)
374 {
375         /* TODO */
376         return api_new_api_cb(closure, api, info, noconcurrency, preinit, preinit_closure);
377 }
378 /**********************************************
379 * vectors
380 **********************************************/
381 static const struct afb_daemon_itf daemon_itf = {
382         .vverbose_v1 = old_vverbose_cb,
383         .vverbose_v2 = vverbose_cb,
384         .event_make = event_make_cb,
385         .event_broadcast = event_broadcast_cb,
386         .get_event_loop = afb_systemd_get_event_loop,
387         .get_user_bus = afb_systemd_get_user_bus,
388         .get_system_bus = afb_systemd_get_system_bus,
389         .rootdir_get_fd = afb_common_rootdir_get_fd,
390         .rootdir_open_locale = rootdir_open_locale_cb,
391         .queue_job = queue_job_cb,
392         .unstore_req = unstore_req_cb,
393         .require_api = require_api_cb,
394         .rename_api = rename_api_cb,
395         .new_api = api_new_api_cb,
396 };
397
398 static const struct afb_daemon_itf hooked_daemon_itf = {
399         .vverbose_v1 = hooked_old_vverbose_cb,
400         .vverbose_v2 = hooked_vverbose_cb,
401         .event_make = hooked_event_make_cb,
402         .event_broadcast = hooked_event_broadcast_cb,
403         .get_event_loop = hooked_get_event_loop,
404         .get_user_bus = hooked_get_user_bus,
405         .get_system_bus = hooked_get_system_bus,
406         .rootdir_get_fd = hooked_rootdir_get_fd,
407         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
408         .queue_job = hooked_queue_job_cb,
409         .unstore_req = hooked_unstore_req_cb,
410         .require_api = hooked_require_api_cb,
411         .rename_api = hooked_rename_api_cb,
412         .new_api = hooked_api_new_api_cb,
413 };
414
415 /*************************************************************************************************************
416  *************************************************************************************************************
417  *************************************************************************************************************
418  *************************************************************************************************************
419                                            F R O M     S V C
420  *************************************************************************************************************
421  *************************************************************************************************************
422  *************************************************************************************************************
423  *************************************************************************************************************/
424
425 /* the common session for services sharing their session */
426 static struct afb_session *common_session;
427
428 /*************************************************************************************************************
429  *************************************************************************************************************
430  *************************************************************************************************************
431  *************************************************************************************************************
432                                            F R O M     S V C
433  *************************************************************************************************************
434  *************************************************************************************************************
435  *************************************************************************************************************
436  *************************************************************************************************************/
437
438 /*
439  * Structure for requests initiated by the service
440  */
441 struct call_req
442 {
443         struct afb_xreq xreq;
444
445         struct afb_export *export;
446
447         /* the args */
448         union {
449                 void (*callback)(void*, int, struct json_object*);
450                 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
451         };
452         void *closure;
453
454         /* sync */
455         struct jobloop *jobloop;
456         struct json_object *result;
457         int status;
458 };
459
460 /*
461  * destroys the call_req
462  */
463 static void callreq_destroy(struct afb_xreq *xreq)
464 {
465         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
466
467         afb_context_disconnect(&callreq->xreq.context);
468         json_object_put(callreq->xreq.json);
469         afb_cred_unref(callreq->xreq.cred);
470         free(callreq);
471 }
472
473 static void callreq_reply_async(struct afb_xreq *xreq, int status, json_object *obj)
474 {
475         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
476         if (callreq->callback)
477                 callreq->callback(callreq->closure, status, obj);
478         json_object_put(obj);
479 }
480
481 static void callreq_reply_async_dynapi(struct afb_xreq *xreq, int status, json_object *obj)
482 {
483         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
484         if (callreq->callback_dynapi)
485                 callreq->callback_dynapi(callreq->closure, status, obj, to_dynapi(callreq->export));
486         json_object_put(obj);
487 }
488
489 static void callreq_sync_leave(struct call_req *callreq)
490 {
491         struct jobloop *jobloop = callreq->jobloop;
492
493         if (jobloop) {
494                 callreq->jobloop = NULL;
495                 jobs_leave(jobloop);
496         }
497 }
498
499 static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj)
500 {
501         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
502         callreq->status = status;
503         callreq->result = obj;
504         callreq_sync_leave(callreq);
505 }
506
507 static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
508 {
509         struct call_req *callreq = closure;
510
511         if (!signum) {
512                 callreq->jobloop = jobloop;
513                 afb_xreq_process(&callreq->xreq, callreq->export->apiset);
514         } else {
515                 callreq->result = afb_msg_json_internal_error();
516                 callreq->status = -1;
517                 callreq_sync_leave(callreq);
518         }
519 }
520
521 /* interface for requests of services */
522 const struct afb_xreq_query_itf afb_export_xreq_async_itf = {
523         .unref = callreq_destroy,
524         .reply = callreq_reply_async
525 };
526
527 /* interface for requests of services */
528 const struct afb_xreq_query_itf afb_export_xreq_async_dynapi_itf = {
529         .unref = callreq_destroy,
530         .reply = callreq_reply_async_dynapi
531 };
532
533 /* interface for requests of services */
534 const struct afb_xreq_query_itf afb_export_xreq_sync_itf = {
535         .unref = callreq_destroy,
536         .reply = callreq_reply_sync
537 };
538
539 /*
540  * create an call_req
541  */
542 static struct call_req *callreq_create(
543                 struct afb_export *export,
544                 const char *api,
545                 const char *verb,
546                 struct json_object *args,
547                 const struct afb_xreq_query_itf *itf)
548 {
549         struct call_req *callreq;
550         size_t lenapi, lenverb;
551         char *copy;
552
553         /* allocates the request */
554         lenapi = 1 + strlen(api);
555         lenverb = 1 + strlen(verb);
556         callreq = malloc(lenapi + lenverb + sizeof *callreq);
557         if (callreq != NULL) {
558                 /* initialises the request */
559                 afb_xreq_init(&callreq->xreq, itf);
560                 afb_context_init(&callreq->xreq.context, export->session, NULL);
561                 callreq->xreq.context.validated = 1;
562                 copy = (char*)&callreq[1];
563                 memcpy(copy, api, lenapi);
564                 callreq->xreq.request.api = copy;
565                 copy = &copy[lenapi];
566                 memcpy(copy, verb, lenverb);
567                 callreq->xreq.request.verb = copy;
568                 callreq->xreq.listener = export->listener;
569                 callreq->xreq.json = args;
570                 callreq->export = export;
571         }
572         return callreq;
573 }
574
575 /*
576  * Initiates a call for the service
577  */
578 static void svc_call(
579                 void *closure,
580                 const char *api,
581                 const char *verb,
582                 struct json_object *args,
583                 void (*callback)(void*, int, struct json_object*),
584                 void *cbclosure)
585 {
586         struct afb_export *export = closure;
587         struct call_req *callreq;
588         struct json_object *ierr;
589
590         /* allocates the request */
591         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_itf);
592         if (callreq == NULL) {
593                 ERROR("out of memory");
594                 json_object_put(args);
595                 ierr = afb_msg_json_internal_error();
596                 if (callback)
597                         callback(cbclosure, -1, ierr);
598                 json_object_put(ierr);
599                 return;
600         }
601
602         /* initialises the request */
603         callreq->jobloop = NULL;
604         callreq->callback = callback;
605         callreq->closure = cbclosure;
606
607         /* terminates and frees ressources if needed */
608         afb_xreq_process(&callreq->xreq, export->apiset);
609 }
610
611 static void svc_call_dynapi(
612                 struct afb_dynapi *dynapi,
613                 const char *api,
614                 const char *verb,
615                 struct json_object *args,
616                 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
617                 void *cbclosure)
618 {
619         struct afb_export *export = from_dynapi(dynapi);
620         struct call_req *callreq;
621         struct json_object *ierr;
622
623         /* allocates the request */
624         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_dynapi_itf);
625         if (callreq == NULL) {
626                 ERROR("out of memory");
627                 json_object_put(args);
628                 ierr = afb_msg_json_internal_error();
629                 if (callback)
630                         callback(cbclosure, -1, ierr, to_dynapi(export));
631                 json_object_put(ierr);
632                 return;
633         }
634
635         /* initialises the request */
636         callreq->jobloop = NULL;
637         callreq->callback_dynapi = callback;
638         callreq->closure = cbclosure;
639
640         /* terminates and frees ressources if needed */
641         afb_xreq_process(&callreq->xreq, export->apiset);
642 }
643
644 static int svc_call_sync(
645                 void *closure,
646                 const char *api,
647                 const char *verb,
648                 struct json_object *args,
649                 struct json_object **result)
650 {
651         struct afb_export *export = closure;
652         struct call_req *callreq;
653         struct json_object *resu;
654         int rc;
655
656         /* allocates the request */
657         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf);
658         if (callreq == NULL) {
659                 ERROR("out of memory");
660                 errno = ENOMEM;
661                 json_object_put(args);
662                 resu = afb_msg_json_internal_error();
663                 rc = -1;
664         } else {
665                 /* initialises the request */
666                 callreq->jobloop = NULL;
667                 callreq->callback = NULL;
668                 callreq->result = NULL;
669                 callreq->status = 0;
670                 afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
671                 rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
672                 if (rc >= 0)
673                         rc = callreq->status;
674                 resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error();
675                 afb_xreq_unhooked_unref(&callreq->xreq);
676         }
677         if (result)
678                 *result = resu;
679         else
680                 json_object_put(resu);
681         return rc;
682 }
683
684 struct hooked_call
685 {
686         struct afb_export *export;
687         union {
688                 void (*callback)(void*, int, struct json_object*);
689                 void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*);
690         };
691         void *cbclosure;
692 };
693
694 static void svc_hooked_call_result(void *closure, int status, struct json_object *result)
695 {
696         struct hooked_call *hc = closure;
697         afb_hook_svc_call_result(hc->export, status, result);
698         hc->callback(hc->cbclosure, status, result);
699         free(hc);
700 }
701
702 static void svc_hooked_call_dynapi_result(void *closure, int status, struct json_object *result, struct afb_dynapi *dynapi)
703 {
704         struct hooked_call *hc = closure;
705         afb_hook_svc_call_result(hc->export, status, result);
706         hc->callback_dynapi(hc->cbclosure, status, result, dynapi);
707         free(hc);
708 }
709
710 static void svc_hooked_call(
711                 void *closure,
712                 const char *api,
713                 const char *verb,
714                 struct json_object *args,
715                 void (*callback)(void*, int, struct json_object*),
716                 void *cbclosure)
717 {
718         struct afb_export *export = closure;
719         struct hooked_call *hc;
720
721         if (export->hooksvc & afb_hook_flag_svc_call)
722                 afb_hook_svc_call(export, api, verb, args);
723
724         if (export->hooksvc & afb_hook_flag_svc_call_result) {
725                 hc = malloc(sizeof *hc);
726                 if (!hc)
727                         WARNING("allocation failed");
728                 else {
729                         hc->export = export;
730                         hc->callback = callback;
731                         hc->cbclosure = cbclosure;
732                         callback = svc_hooked_call_result;
733                         cbclosure = hc;
734                 }
735         }
736         svc_call(closure, api, verb, args, callback, cbclosure);
737 }
738
739 static void svc_hooked_call_dynapi(
740                 struct afb_dynapi *dynapi,
741                 const char *api,
742                 const char *verb,
743                 struct json_object *args,
744                 void (*callback)(void*, int, struct json_object*, struct afb_dynapi*),
745                 void *cbclosure)
746 {
747         struct afb_export *export = from_dynapi(dynapi);
748         struct hooked_call *hc;
749
750         if (export->hooksvc & afb_hook_flag_svc_call)
751                 afb_hook_svc_call(export, api, verb, args);
752
753         if (export->hooksvc & afb_hook_flag_svc_call_result) {
754                 hc = malloc(sizeof *hc);
755                 if (!hc)
756                         WARNING("allocation failed");
757                 else {
758                         hc->export = export;
759                         hc->callback_dynapi = callback;
760                         hc->cbclosure = cbclosure;
761                         callback = svc_hooked_call_dynapi_result;
762                         cbclosure = hc;
763                 }
764         }
765         svc_call_dynapi(dynapi, api, verb, args, callback, cbclosure);
766 }
767
768 static int svc_hooked_call_sync(
769                 void *closure,
770                 const char *api,
771                 const char *verb,
772                 struct json_object *args,
773                 struct json_object **result)
774 {
775         struct afb_export *export = closure;
776         struct json_object *resu;
777         int rc;
778
779         if (export->hooksvc & afb_hook_flag_svc_callsync)
780                 afb_hook_svc_callsync(export, api, verb, args);
781
782         rc = svc_call_sync(closure, api, verb, args, &resu);
783
784         if (export->hooksvc & afb_hook_flag_svc_callsync_result)
785                 afb_hook_svc_callsync_result(export, rc, resu);
786
787         if (result)
788                 *result = resu;
789         else
790                 json_object_put(resu);
791
792         return rc;
793 }
794
795 /* the interface for services */
796 static const struct afb_service_itf service_itf = {
797         .call = svc_call,
798         .call_sync = svc_call_sync
799 };
800
801 /* the interface for services */
802 static const struct afb_service_itf hooked_service_itf = {
803         .call = svc_hooked_call,
804         .call_sync = svc_hooked_call_sync
805 };
806
807 /*************************************************************************************************************
808  *************************************************************************************************************
809  *************************************************************************************************************
810  *************************************************************************************************************
811                                            F R O M     D Y N A P I
812  *************************************************************************************************************
813  *************************************************************************************************************
814  *************************************************************************************************************
815  *************************************************************************************************************/
816
817 static int api_set_verbs_v2_cb(
818                 struct afb_dynapi *dynapi,
819                 const struct afb_verb_v2 *verbs)
820 {
821         struct afb_export *export = from_dynapi(dynapi);
822
823         if (export->apidyn) {
824                 afb_api_dyn_set_verbs_v2(export->apidyn, verbs);
825                 return 0;
826         }
827
828         errno = EPERM;
829         return -1;
830 }
831
832 static int api_add_verb_cb(
833                 struct afb_dynapi *dynapi,
834                 const char *verb,
835                 const char *info,
836                 void (*callback)(struct afb_request *request),
837                 void *vcbdata,
838                 const struct afb_auth *auth,
839                 uint32_t session)
840 {
841         struct afb_export *export = from_dynapi(dynapi);
842
843         if (export->apidyn)
844                 return afb_api_dyn_add_verb(export->apidyn, verb, info, callback, vcbdata, auth, session);
845
846         errno = EPERM;
847         return -1;
848 }
849
850 static int api_sub_verb_cb(
851                 struct afb_dynapi *dynapi,
852                 const char *verb)
853 {
854         struct afb_export *export = from_dynapi(dynapi);
855
856         if (export->apidyn)
857                 return afb_api_dyn_sub_verb(export->apidyn, verb);
858
859         errno = EPERM;
860         return -1;
861 }
862
863 static int api_set_on_event_cb(
864                 struct afb_dynapi *dynapi,
865                 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
866 {
867         struct afb_export *export = from_dynapi(dynapi);
868         return afb_export_handle_events_vdyn(export, onevent);
869 }
870
871 static int api_set_on_init_cb(
872                 struct afb_dynapi *dynapi,
873                 int (*oninit)(struct afb_dynapi *dynapi))
874 {
875         struct afb_export *export = from_dynapi(dynapi);
876
877         return afb_export_handle_init_vdyn(export, oninit);
878 }
879
880 static void api_seal_cb(
881                 struct afb_dynapi *dynapi)
882 {
883         struct afb_export *export = from_dynapi(dynapi);
884
885         export->apidyn = NULL;
886 }
887
888 static int hooked_api_set_verbs_v2_cb(
889                 struct afb_dynapi *dynapi,
890                 const struct afb_verb_v2 *verbs)
891 {
892         /* TODO */
893         return api_set_verbs_v2_cb(dynapi, verbs);
894 }
895
896 static int hooked_api_add_verb_cb(
897                 struct afb_dynapi *dynapi,
898                 const char *verb,
899                 const char *info,
900                 void (*callback)(struct afb_request *request),
901                 void *vcbdata,
902                 const struct afb_auth *auth,
903                 uint32_t session)
904 {
905         /* TODO */
906         return api_add_verb_cb(dynapi, verb, info, callback, vcbdata, auth, session);
907 }
908
909 static int hooked_api_sub_verb_cb(
910                 struct afb_dynapi *dynapi,
911                 const char *verb)
912 {
913         /* TODO */
914         return api_sub_verb_cb(dynapi, verb);
915 }
916
917 static int hooked_api_set_on_event_cb(
918                 struct afb_dynapi *dynapi,
919                 void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
920 {
921         /* TODO */
922         return api_set_on_event_cb(dynapi, onevent);
923 }
924
925 static int hooked_api_set_on_init_cb(
926                 struct afb_dynapi *dynapi,
927                 int (*oninit)(struct afb_dynapi *dynapi))
928 {
929         /* TODO */
930         return api_set_on_init_cb(dynapi, oninit);
931 }
932
933 static void hooked_api_seal_cb(
934                 struct afb_dynapi *dynapi)
935 {
936         /* TODO */
937         api_seal_cb(dynapi);
938 }
939
940 static const struct afb_dynapi_itf dynapi_itf = {
941
942         .vverbose = (void*)vverbose_cb,
943
944         .get_event_loop = afb_systemd_get_event_loop,
945         .get_user_bus = afb_systemd_get_user_bus,
946         .get_system_bus = afb_systemd_get_system_bus,
947         .rootdir_get_fd = afb_common_rootdir_get_fd,
948         .rootdir_open_locale = rootdir_open_locale_cb,
949         .queue_job = queue_job_cb,
950
951         .require_api = require_api_cb,
952         .rename_api = rename_api_cb,
953
954         .event_broadcast = event_broadcast_cb,
955         .eventid_make = eventid_make_cb,
956
957         .call = svc_call_dynapi,
958         .call_sync = svc_call_sync,
959
960         .api_new_api = api_new_api_cb,
961         .api_set_verbs_v2 = api_set_verbs_v2_cb,
962         .api_add_verb = api_add_verb_cb,
963         .api_sub_verb = api_sub_verb_cb,
964         .api_set_on_event = api_set_on_event_cb,
965         .api_set_on_init = api_set_on_init_cb,
966         .api_seal = api_seal_cb,
967 };
968
969 static const struct afb_dynapi_itf hooked_dynapi_itf = {
970
971         .vverbose = hooked_vverbose_cb,
972
973         .get_event_loop = hooked_get_event_loop,
974         .get_user_bus = hooked_get_user_bus,
975         .get_system_bus = hooked_get_system_bus,
976         .rootdir_get_fd = hooked_rootdir_get_fd,
977         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
978         .queue_job = hooked_queue_job_cb,
979
980         .require_api = hooked_require_api_cb,
981         .rename_api = hooked_rename_api_cb,
982
983         .event_broadcast = hooked_event_broadcast_cb,
984         .eventid_make = hooked_eventid_make_cb,
985
986         .call = svc_hooked_call_dynapi,
987         .call_sync = svc_hooked_call_sync,
988
989         .api_new_api = hooked_api_new_api_cb,
990         .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb,
991         .api_add_verb = hooked_api_add_verb_cb,
992         .api_sub_verb = hooked_api_sub_verb_cb,
993         .api_set_on_event = hooked_api_set_on_event_cb,
994         .api_set_on_init = hooked_api_set_on_init_cb,
995         .api_seal = hooked_api_seal_cb,
996 };
997
998 /*************************************************************************************************************
999  *************************************************************************************************************
1000  *************************************************************************************************************
1001  *************************************************************************************************************
1002                                            F R O M     S V C
1003  *************************************************************************************************************
1004  *************************************************************************************************************
1005  *************************************************************************************************************
1006  *************************************************************************************************************/
1007
1008 /*
1009  * Propagates the event to the service
1010  */
1011 static void export_on_event_v12(void *closure, const char *event, int eventid, struct json_object *object)
1012 {
1013         struct afb_export *export = closure;
1014
1015         if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1016                 afb_hook_svc_on_event_before(export, event, eventid, object);
1017         export->on_event.v12(event, object);
1018         if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1019                 afb_hook_svc_on_event_after(export, event, eventid, object);
1020         json_object_put(object);
1021 }
1022
1023 /* the interface for events */
1024 static const struct afb_evt_itf evt_v12_itf = {
1025         .broadcast = export_on_event_v12,
1026         .push = export_on_event_v12
1027 };
1028
1029 /*
1030  * Propagates the event to the service
1031  */
1032 static void export_on_event_vdyn(void *closure, const char *event, int eventid, struct json_object *object)
1033 {
1034         struct afb_export *export = closure;
1035
1036         if (export->hooksvc & afb_hook_flag_svc_on_event_before)
1037                 afb_hook_svc_on_event_before(export, event, eventid, object);
1038         export->on_event.vdyn(to_dynapi(export), event, object);
1039         if (export->hooksvc & afb_hook_flag_svc_on_event_after)
1040                 afb_hook_svc_on_event_after(export, event, eventid, object);
1041         json_object_put(object);
1042 }
1043
1044 /* the interface for events */
1045 static const struct afb_evt_itf evt_vdyn_itf = {
1046         .broadcast = export_on_event_vdyn,
1047         .push = export_on_event_vdyn
1048 };
1049
1050 /*************************************************************************************************************
1051  *************************************************************************************************************
1052  *************************************************************************************************************
1053  *************************************************************************************************************
1054                                            M E R G E D
1055  *************************************************************************************************************
1056  *************************************************************************************************************
1057  *************************************************************************************************************
1058  *************************************************************************************************************/
1059
1060 static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
1061 {
1062         struct afb_export *export;
1063
1064         /* session shared with other exports */
1065         if (common_session == NULL) {
1066                 common_session = afb_session_create (0);
1067                 if (common_session == NULL)
1068                         return NULL;
1069         }
1070         export = calloc(1, sizeof *export);
1071         if (!export)
1072                 errno = ENOMEM;
1073         else {
1074                 memset(export, 0, sizeof *export);
1075                 export->apiname = strdup(apiname);
1076                 export->dynapi.apiname = export->apiname;
1077                 export->version = version;
1078                 export->state = Api_State_Pre_Init;
1079                 export->session = afb_session_addref(common_session);
1080                 export->apiset = afb_apiset_addref(apiset);
1081         }
1082         return export;
1083 }
1084
1085 void afb_export_destroy(struct afb_export *export)
1086 {
1087         if (export) {
1088                 if (export->listener != NULL)
1089                         afb_evt_listener_unref(export->listener);
1090                 afb_session_unref(export->session);
1091                 afb_apiset_unref(export->apiset);
1092                 free(export->apiname);
1093                 free(export);
1094         }
1095 }
1096
1097 struct afb_export *afb_export_create_v1(struct afb_apiset *apiset, const char *apiname, int (*init)(struct afb_service), void (*onevent)(const char*, struct json_object*))
1098 {
1099         struct afb_export *export = create(apiset, apiname, Api_Version_1);
1100         if (export) {
1101                 export->init.v1 = init;
1102                 export->on_event.v12 = onevent;
1103                 export->export.v1.mode = AFB_MODE_LOCAL;
1104                 export->export.v1.daemon.closure = export;
1105                 afb_export_verbosity_set(export, verbosity);
1106                 afb_export_update_hook(export);
1107         }
1108         return export;
1109 }
1110
1111 struct afb_export *afb_export_create_v2(struct afb_apiset *apiset, const char *apiname, struct afb_binding_data_v2 *data, int (*init)(), void (*onevent)(const char*, struct json_object*))
1112 {
1113         struct afb_export *export = create(apiset, apiname, Api_Version_2);
1114         if (export) {
1115                 export->init.v2 = init;
1116                 export->on_event.v12 = onevent;
1117                 export->export.v2 = data;
1118                 data->daemon.closure = export;
1119                 data->service.closure = export;
1120                 afb_export_verbosity_set(export, verbosity);
1121                 afb_export_update_hook(export);
1122         }
1123         return export;
1124 }
1125
1126 struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *apidyn)
1127 {
1128         struct afb_export *export = create(apiset, apiname, Api_Version_Dyn);
1129         if (export) {
1130                 export->apidyn = apidyn;
1131                 afb_export_verbosity_set(export, verbosity);
1132                 afb_export_update_hook(export);
1133         }
1134         return export;
1135 }
1136
1137 void afb_export_rename(struct afb_export *export, const char *apiname)
1138 {
1139         free(export->apiname);
1140         export->apiname = strdup(apiname);
1141         export->dynapi.apiname = export->apiname;
1142         afb_export_update_hook(export);
1143 }
1144
1145 const char *afb_export_apiname(const struct afb_export *export)
1146 {
1147         return export->apiname;
1148 }
1149
1150 void afb_export_update_hook(struct afb_export *export)
1151 {
1152         export->hookditf = afb_hook_flags_ditf(export->apiname);
1153         export->hooksvc = afb_hook_flags_svc(export->apiname);
1154         export->dynapi.itf = export->hookditf|export->hooksvc ? &hooked_dynapi_itf : &dynapi_itf;
1155
1156         switch (export->version) {
1157         case Api_Version_1:
1158                 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1159                 break;
1160         case Api_Version_2:
1161                 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
1162                 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
1163                 break;
1164         }
1165 }
1166
1167 struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export)
1168 {
1169         return export->version == Api_Version_1 ? &export->export.v1 : NULL;
1170 }
1171
1172 int afb_export_unshare_session(struct afb_export *export)
1173 {
1174         if (export->session == common_session) {
1175                 export->session = afb_session_create (0);
1176                 if (export->session)
1177                         afb_session_unref(common_session);
1178                 else {
1179                         export->session = common_session;
1180                         return -1;
1181                 }
1182         }
1183         return 0;
1184 }
1185
1186 void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset)
1187 {
1188         struct afb_apiset *prvset = export->apiset;
1189         export->apiset = afb_apiset_addref(apiset);
1190         afb_apiset_unref(prvset);
1191 }
1192
1193 struct afb_apiset *afb_export_get_apiset(struct afb_export *export)
1194 {
1195         return export->apiset;
1196 }
1197
1198 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
1199 {
1200         /* check version */
1201         switch (export->version) {
1202         case Api_Version_1: case Api_Version_2: break;
1203         default:
1204                 ERROR("invalid version 12 for API %s", export->apiname);
1205                 errno = EINVAL;
1206                 return -1;
1207         }
1208
1209         /* set the event handler */
1210         if (!on_event) {
1211                 if (export->listener) {
1212                         afb_evt_listener_unref(export->listener);
1213                         export->listener = NULL;
1214                 }
1215                 export->on_event.v12 = on_event;
1216         } else {
1217                 export->on_event.v12 = on_event;
1218                 if (!export->listener) {
1219                         export->listener = afb_evt_listener_create(&evt_v12_itf, export);
1220                         if (export->listener == NULL)
1221                                 return -1;
1222                 }
1223         }
1224         return 0;
1225 }
1226
1227 int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object))
1228 {
1229         /* check version */
1230         switch (export->version) {
1231         case Api_Version_Dyn: break;
1232         default:
1233                 ERROR("invalid version Dyn for API %s", export->apiname);
1234                 errno = EINVAL;
1235                 return -1;
1236         }
1237
1238         /* set the event handler */
1239         if (!on_event) {
1240                 if (export->listener) {
1241                         afb_evt_listener_unref(export->listener);
1242                         export->listener = NULL;
1243                 }
1244                 export->on_event.vdyn = on_event;
1245         } else {
1246                 export->on_event.vdyn = on_event;
1247                 if (!export->listener) {
1248                         export->listener = afb_evt_listener_create(&evt_vdyn_itf, export);
1249                         if (export->listener == NULL)
1250                                 return -1;
1251                 }
1252         }
1253         return 0;
1254 }
1255
1256 int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi))
1257 {
1258         if (export->state != Api_State_Pre_Init) {
1259                 ERROR("[API %s] Bad call to 'afb_dynapi_on_init', must be in PreInit", export->apiname);
1260                 errno = EINVAL;
1261                 return -1;
1262         }
1263
1264         export->init.vdyn  = oninit;
1265         return 0;
1266 }
1267
1268 /*
1269  * Starts a new service (v1)
1270  */
1271 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
1272 {
1273         return regfun(&export->export.v1);
1274 }
1275
1276 int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure)
1277 {
1278         return preinit(closure, to_dynapi(export));
1279 }
1280
1281 int afb_export_verbosity_get(const struct afb_export *export)
1282 {
1283         return export->dynapi.verbosity;
1284 }
1285
1286 void afb_export_verbosity_set(struct afb_export *export, int level)
1287 {
1288         export->dynapi.verbosity = level;
1289         switch (export->version) {
1290         case Api_Version_1: export->export.v1.verbosity = level; break;
1291         case Api_Version_2: export->export.v2->verbosity = level; break;
1292         }
1293 }
1294
1295 /*************************************************************************************************************
1296  *************************************************************************************************************
1297  *************************************************************************************************************
1298  *************************************************************************************************************
1299                                            N E W
1300  *************************************************************************************************************
1301  *************************************************************************************************************
1302  *************************************************************************************************************
1303  *************************************************************************************************************/
1304
1305 int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
1306 {
1307         int rc;
1308
1309         /* check state */
1310         if (export->state != Api_State_Pre_Init) {
1311                 /* not an error when onneed */
1312                 if (onneed != 0)
1313                         goto done;
1314
1315                 /* already started: it is an error */
1316                 ERROR("Service of API %s already started", export->apiname);
1317                 return -1;
1318         }
1319
1320         /* unshare the session if asked */
1321         if (!share_session) {
1322                 rc = afb_export_unshare_session(export);
1323                 if (rc < 0) {
1324                         ERROR("Can't unshare the session for %s", export->apiname);
1325                         return -1;
1326                 }
1327         }
1328
1329         /* set event handling */
1330         switch (export->version) {
1331         case Api_Version_1:
1332         case Api_Version_2:
1333                 rc = afb_export_handle_events_v12(export, export->on_event.v12);
1334                 break;
1335         default:
1336                 rc = 0;
1337                 break;
1338         }
1339         if (rc < 0) {
1340                 ERROR("Can't set event handler for %s", export->apiname);
1341                 return -1;
1342         }
1343
1344         /* Starts the service */
1345         if (export->hooksvc & afb_hook_flag_svc_start_before)
1346                 afb_hook_svc_start_before(export);
1347         export->state = Api_State_Init;
1348         switch (export->version) {
1349         case Api_Version_1:
1350                 rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
1351                 break;
1352         case Api_Version_2:
1353                 rc = export->init.v2 ? export->init.v2() : 0;
1354                 break;
1355         case Api_Version_Dyn:
1356                 rc = export->init.vdyn ? export->init.vdyn(to_dynapi(export)) : 0;
1357                 break;
1358         default:
1359                 break;
1360         }
1361         export->state = Api_State_Run;
1362         if (export->hooksvc & afb_hook_flag_svc_start_after)
1363                 afb_hook_svc_start_after(export, rc);
1364         if (rc < 0) {
1365                 /* initialisation error */
1366                 ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);
1367                 return rc;
1368         }
1369
1370 done:
1371         return 0;
1372 }
1373