Deprecate internal use of afb_event
[src/app-framework-binder.git] / src / afb-export.c
1 /*
2  * Copyright (C) 2016, 2017 "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 #include <afb/afb-binding-v1.h>
27 #include <afb/afb-binding-v2.h>
28
29 #include "afb-api.h"
30 #include "afb-apiset.h"
31 #include "afb-common.h"
32 #include "afb-cred.h"
33 #include "afb-evt.h"
34 #include "afb-export.h"
35 #include "afb-hook.h"
36 #include "afb-msg-json.h"
37 #include "afb-session.h"
38 #include "afb-xreq.h"
39 #include "jobs.h"
40 #include "verbose.h"
41
42
43 /*************************************************************************
44  * internal types and structures
45  ************************************************************************/
46
47 enum afb_api_version
48 {
49         Api_Version_None = 0,
50         Api_Version_1 = 1,
51         Api_Version_2 = 2,
52         Api_Version_3 = 3
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         /* name of the api */
65         char *apiname;
66
67         /* version of the api */
68         unsigned version: 4;
69
70         /* current state */
71         unsigned state: 4;
72
73         /* hooking flags */
74         int hookditf;
75         int hooksvc;
76
77         /* session for service */
78         struct afb_session *session;
79
80         /* apiset for service */
81         struct afb_apiset *apiset;
82
83         /* event listener for service or NULL */
84         struct afb_evt_listener *listener;
85
86         /* start function */
87         union {
88                 int (*v1)(struct afb_service);
89                 int (*v2)();
90         } init;
91
92         /* event handling */
93         union {
94                 void (*v12)(const char *event, struct json_object *object);
95         } on_event;
96
97         /* exported data */
98         union {
99                 struct afb_binding_interface_v1 v1;
100                 struct afb_binding_data_v2 *v2;
101         } export;
102 };
103
104 /*************************************************************************************************************
105  *************************************************************************************************************
106  *************************************************************************************************************
107  *************************************************************************************************************
108                                            F R O M     D I T F
109  *************************************************************************************************************
110  *************************************************************************************************************
111  *************************************************************************************************************
112  *************************************************************************************************************/
113
114 /**********************************************
115 * normal flow
116 **********************************************/
117 static void vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
118 {
119         char *p;
120         struct afb_export *export = closure;
121
122         if (!fmt || vasprintf(&p, fmt, args) < 0)
123                 vverbose(level, file, line, function, fmt, args);
124         else {
125                 verbose(level, file, line, function, "[API %s] %s", export->apiname, p);
126                 free(p);
127         }
128 }
129
130 static void old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
131 {
132         vverbose_cb(closure, level, file, line, NULL, fmt, args);
133 }
134
135 static struct afb_event event_make_cb(void *closure, const char *name)
136 {
137         size_t plen, nlen;
138         char *event;
139         struct afb_export *export = closure;
140         struct afb_eventid *eventid;
141
142         /* check daemon state */
143         if (export->state == Api_State_Pre_Init) {
144                 ERROR("[API %s] Bad call to 'afb_daemon_event_make(%s)', must not be in PreInit", export->apiname, name);
145                 errno = EINVAL;
146                 return (struct afb_event){ .itf = NULL, .closure = NULL };
147         }
148
149         /* makes the event name */
150         plen = strlen(export->apiname);
151         nlen = strlen(name);
152         event = alloca(nlen + plen + 2);
153         memcpy(event, export->apiname, plen);
154         event[plen] = '/';
155         memcpy(event + plen + 1, name, nlen + 1);
156
157         /* create the event */
158         eventid = afb_evt_create_event(event);
159         return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
160 }
161
162 static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
163 {
164         size_t plen, nlen;
165         char *event;
166         struct afb_export *export = closure;
167
168         /* check daemon state */
169         if (export->state == Api_State_Pre_Init) {
170                 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));
171                 errno = EINVAL;
172                 return 0;
173         }
174
175         /* makes the event name */
176         plen = strlen(export->apiname);
177         nlen = strlen(name);
178         event = alloca(nlen + plen + 2);
179         memcpy(event, export->apiname, plen);
180         event[plen] = '/';
181         memcpy(event + plen + 1, name, nlen + 1);
182
183         /* broadcast the event */
184         return afb_evt_broadcast(event, object);
185 }
186
187 static int rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
188 {
189         return afb_common_rootdir_open_locale(filename, flags, locale);
190 }
191
192 static int queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
193 {
194         return jobs_queue(group, timeout, callback, argument);
195 }
196
197 static struct afb_req unstore_req_cb(void *closure, struct afb_stored_req *sreq)
198 {
199         return afb_xreq_unstore(sreq);
200 }
201
202 static int require_api_cb(void *closure, const char *name, int initialized)
203 {
204         struct afb_export *export = closure;
205         if (export->state != Api_State_Init) {
206                 ERROR("[API %s] Bad call to 'afb_daemon_require(%s, %d)', must be in Init", export->apiname, name, initialized);
207                 errno = EINVAL;
208                 return -1;
209         }
210         return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
211 }
212
213 static int rename_api_cb(void *closure, const char *name)
214 {
215         struct afb_export *export = closure;
216         if (export->state != Api_State_Pre_Init) {
217                 ERROR("[API %s] Bad call to 'afb_daemon_rename(%s)', must be in PreInit", export->apiname, name);
218                 errno = EINVAL;
219                 return -1;
220         }
221         if (!afb_api_is_valid_name(name)) {
222                 ERROR("[API %s] Can't rename to %s: bad API name", export->apiname, name);
223                 errno = EINVAL;
224                 return -1;
225         }
226         NOTICE("[API %s] renamed to [API %s]", export->apiname, name);
227         afb_export_rename(export, name);
228         return 0;
229 }
230
231 /**********************************************
232 * hooked flow
233 **********************************************/
234 static void hooked_vverbose_cb(void *closure, int level, const char *file, int line, const char *function, const char *fmt, va_list args)
235 {
236         struct afb_export *export = closure;
237         va_list ap;
238         va_copy(ap, args);
239         vverbose_cb(closure, level, file, line, function, fmt, args);
240         afb_hook_ditf_vverbose(export, level, file, line, function, fmt, ap);
241         va_end(ap);
242 }
243
244 static void hooked_old_vverbose_cb(void *closure, int level, const char *file, int line, const char *fmt, va_list args)
245 {
246         hooked_vverbose_cb(closure, level, file, line, NULL, fmt, args);
247 }
248
249 static struct afb_event hooked_event_make_cb(void *closure, const char *name)
250 {
251         struct afb_export *export = closure;
252         struct afb_event r = event_make_cb(closure, name);
253         afb_hook_ditf_event_make(export, name, r.closure);
254         return r;
255 }
256
257 static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
258 {
259         int r;
260         struct afb_export *export = closure;
261         json_object_get(object);
262         afb_hook_ditf_event_broadcast_before(export, name, json_object_get(object));
263         r = event_broadcast_cb(closure, name, object);
264         afb_hook_ditf_event_broadcast_after(export, name, object, r);
265         json_object_put(object);
266         return r;
267 }
268
269 static struct sd_event *hooked_get_event_loop(void *closure)
270 {
271         struct afb_export *export = closure;
272         struct sd_event *r = afb_common_get_event_loop();
273         return afb_hook_ditf_get_event_loop(export, r);
274 }
275
276 static struct sd_bus *hooked_get_user_bus(void *closure)
277 {
278         struct afb_export *export = closure;
279         struct sd_bus *r = afb_common_get_user_bus();
280         return afb_hook_ditf_get_user_bus(export, r);
281 }
282
283 static struct sd_bus *hooked_get_system_bus(void *closure)
284 {
285         struct afb_export *export = closure;
286         struct sd_bus *r = afb_common_get_system_bus();
287         return afb_hook_ditf_get_system_bus(export, r);
288 }
289
290 static int hooked_rootdir_get_fd(void *closure)
291 {
292         struct afb_export *export = closure;
293         int r = afb_common_rootdir_get_fd();
294         return afb_hook_ditf_rootdir_get_fd(export, r);
295 }
296
297 static int hooked_rootdir_open_locale_cb(void *closure, const char *filename, int flags, const char *locale)
298 {
299         struct afb_export *export = closure;
300         int r = rootdir_open_locale_cb(closure, filename, flags, locale);
301         return afb_hook_ditf_rootdir_open_locale(export, filename, flags, locale, r);
302 }
303
304 static int hooked_queue_job_cb(void *closure, void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
305 {
306         struct afb_export *export = closure;
307         int r = queue_job_cb(closure, callback, argument, group, timeout);
308         return afb_hook_ditf_queue_job(export, callback, argument, group, timeout, r);
309 }
310
311 static struct afb_req hooked_unstore_req_cb(void *closure, struct afb_stored_req *sreq)
312 {
313         struct afb_export *export = closure;
314         afb_hook_ditf_unstore_req(export, sreq);
315         return unstore_req_cb(closure, sreq);
316 }
317
318 static int hooked_require_api_cb(void *closure, const char *name, int initialized)
319 {
320         int result;
321         struct afb_export *export = closure;
322         afb_hook_ditf_require_api(export, name, initialized);
323         result = require_api_cb(closure, name, initialized);
324         return afb_hook_ditf_require_api_result(export, name, initialized, result);
325 }
326
327 static int hooked_rename_api_cb(void *closure, const char *name)
328 {
329         struct afb_export *export = closure;
330         const char *oldname = export->apiname;
331         int result = rename_api_cb(closure, name);
332         return afb_hook_ditf_rename_api(export, oldname, name, result);
333 }
334
335 /**********************************************
336 * vectors
337 **********************************************/
338 static const struct afb_daemon_itf daemon_itf = {
339         .vverbose_v1 = old_vverbose_cb,
340         .vverbose_v2 = vverbose_cb,
341         .event_make = event_make_cb,
342         .event_broadcast = event_broadcast_cb,
343         .get_event_loop = afb_common_get_event_loop,
344         .get_user_bus = afb_common_get_user_bus,
345         .get_system_bus = afb_common_get_system_bus,
346         .rootdir_get_fd = afb_common_rootdir_get_fd,
347         .rootdir_open_locale = rootdir_open_locale_cb,
348         .queue_job = queue_job_cb,
349         .unstore_req = unstore_req_cb,
350         .require_api = require_api_cb,
351         .rename_api = rename_api_cb
352 };
353
354 static const struct afb_daemon_itf hooked_daemon_itf = {
355         .vverbose_v1 = hooked_old_vverbose_cb,
356         .vverbose_v2 = hooked_vverbose_cb,
357         .event_make = hooked_event_make_cb,
358         .event_broadcast = hooked_event_broadcast_cb,
359         .get_event_loop = hooked_get_event_loop,
360         .get_user_bus = hooked_get_user_bus,
361         .get_system_bus = hooked_get_system_bus,
362         .rootdir_get_fd = hooked_rootdir_get_fd,
363         .rootdir_open_locale = hooked_rootdir_open_locale_cb,
364         .queue_job = hooked_queue_job_cb,
365         .unstore_req = hooked_unstore_req_cb,
366         .require_api = hooked_require_api_cb,
367         .rename_api = hooked_rename_api_cb
368 };
369
370
371 /*************************************************************************************************************
372  *************************************************************************************************************
373  *************************************************************************************************************
374  *************************************************************************************************************
375                                            F R O M     S V C
376  *************************************************************************************************************
377  *************************************************************************************************************
378  *************************************************************************************************************
379  *************************************************************************************************************/
380
381 /* the common session for services sharing their session */
382 static struct afb_session *common_session;
383
384 /*************************************************************************************************************
385  *************************************************************************************************************
386  *************************************************************************************************************
387  *************************************************************************************************************
388                                            F R O M     S V C
389  *************************************************************************************************************
390  *************************************************************************************************************
391  *************************************************************************************************************
392  *************************************************************************************************************/
393
394 /*
395  * Structure for requests initiated by the service
396  */
397 struct call_req
398 {
399         struct afb_xreq xreq;
400
401         struct afb_export *export;
402
403         /* the args */
404         void (*callback)(void*, int, struct json_object*);
405         void *closure;
406
407         /* sync */
408         struct jobloop *jobloop;
409         struct json_object *result;
410         int status;
411         int async;
412 };
413
414 /*
415  * destroys the call_req
416  */
417 static void callreq_destroy(struct afb_xreq *xreq)
418 {
419         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
420
421         afb_context_disconnect(&callreq->xreq.context);
422         json_object_put(callreq->xreq.json);
423         afb_cred_unref(callreq->xreq.cred);
424         free(callreq);
425 }
426
427 static void callreq_reply(struct afb_xreq *xreq, int status, json_object *obj)
428 {
429         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
430         if (callreq->callback)
431                 callreq->callback(callreq->closure, status, obj);
432         json_object_put(obj);
433 }
434
435 static void callreq_sync_leave(struct call_req *callreq)
436 {
437         struct jobloop *jobloop = callreq->jobloop;
438
439         if (jobloop) {
440                 callreq->jobloop = NULL;
441                 jobs_leave(jobloop);
442         }
443 }
444
445 static void callreq_reply_sync(struct afb_xreq *xreq, int status, json_object *obj)
446 {
447         struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq);
448         callreq->status = status;
449         callreq->result = obj;
450         callreq_sync_leave(callreq);
451 }
452
453 static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloop)
454 {
455         struct call_req *callreq = closure;
456
457         if (!signum) {
458                 callreq->jobloop = jobloop;
459                 afb_xreq_process(&callreq->xreq, callreq->export->apiset);
460         } else {
461                 callreq->result = afb_msg_json_internal_error();
462                 callreq->status = -1;
463                 callreq_sync_leave(callreq);
464         }
465 }
466
467 /* interface for requests of services */
468 const struct afb_xreq_query_itf afb_export_xreq_itf = {
469         .unref = callreq_destroy,
470         .reply = callreq_reply
471 };
472
473 /* interface for requests of services */
474 const struct afb_xreq_query_itf afb_export_xreq_sync_itf = {
475         .unref = callreq_destroy,
476         .reply = callreq_reply_sync
477 };
478
479 /*
480  * create an call_req
481  */
482 static struct call_req *callreq_create(struct afb_export *export, const char *api, const char *verb, struct json_object *args, const struct afb_xreq_query_itf *itf)
483 {
484         struct call_req *callreq;
485         size_t lenapi, lenverb;
486         char *copy;
487
488         /* allocates the request */
489         lenapi = 1 + strlen(api);
490         lenverb = 1 + strlen(verb);
491         callreq = malloc(lenapi + lenverb + sizeof *callreq);
492         if (callreq != NULL) {
493                 /* initialises the request */
494                 afb_xreq_init(&callreq->xreq, itf);
495                 afb_context_init(&callreq->xreq.context, export->session, NULL);
496                 callreq->xreq.context.validated = 1;
497                 copy = (char*)&callreq[1];
498                 memcpy(copy, api, lenapi);
499                 callreq->xreq.api = copy;
500                 copy = &copy[lenapi];
501                 memcpy(copy, verb, lenverb);
502                 callreq->xreq.verb = copy;
503                 callreq->xreq.listener = export->listener;
504                 callreq->xreq.json = args;
505                 callreq->export = export;
506         }
507         return callreq;
508 }
509
510 /*
511  * Initiates a call for the service
512  */
513 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)
514 {
515         struct afb_export *export = closure;
516         struct call_req *callreq;
517         struct json_object *ierr;
518
519         /* allocates the request */
520         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_itf);
521         if (callreq == NULL) {
522                 ERROR("out of memory");
523                 json_object_put(args);
524                 ierr = afb_msg_json_internal_error();
525                 if (callback)
526                         callback(cbclosure, -1, ierr);
527                 json_object_put(ierr);
528                 return;
529         }
530
531         /* initialises the request */
532         callreq->jobloop = NULL;
533         callreq->callback = callback;
534         callreq->closure = cbclosure;
535         callreq->async = 1;
536
537         /* terminates and frees ressources if needed */
538         afb_xreq_process(&callreq->xreq, export->apiset);
539 }
540
541 static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args,
542                                 struct json_object **result)
543 {
544         struct afb_export *export = closure;
545         struct call_req *callreq;
546         struct json_object *resu;
547         int rc;
548
549         /* allocates the request */
550         callreq = callreq_create(export, api, verb, args, &afb_export_xreq_sync_itf);
551         if (callreq == NULL) {
552                 ERROR("out of memory");
553                 errno = ENOMEM;
554                 json_object_put(args);
555                 resu = afb_msg_json_internal_error();
556                 rc = -1;
557         } else {
558                 /* initialises the request */
559                 callreq->jobloop = NULL;
560                 callreq->callback = NULL;
561                 callreq->result = NULL;
562                 callreq->status = 0;
563                 callreq->async = 0;
564                 afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
565                 rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
566                 if (rc >= 0)
567                         rc = callreq->status;
568                 resu = (rc >= 0 || callreq->result) ? callreq->result : afb_msg_json_internal_error();
569                 afb_xreq_unhooked_unref(&callreq->xreq);
570         }
571         if (result)
572                 *result = resu;
573         else
574                 json_object_put(resu);
575         return rc;
576 }
577
578 struct hooked_call
579 {
580         struct afb_export *export;
581         void (*callback)(void*, int, struct json_object*);
582         void *cbclosure;
583 };
584
585 static void svc_hooked_call_result(void *closure, int status, struct json_object *result)
586 {
587         struct hooked_call *hc = closure;
588         afb_hook_svc_call_result(hc->export, status, result);
589         hc->callback(hc->cbclosure, status, result);
590         free(hc);
591 }
592
593 static void svc_hooked_call(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *cbclosure)
594 {
595         struct afb_export *export = closure;
596         struct hooked_call *hc;
597
598         if (export->hooksvc & afb_hook_flag_svc_call)
599                 afb_hook_svc_call(export, api, verb, args);
600
601         if (export->hooksvc & afb_hook_flag_svc_call_result) {
602                 hc = malloc(sizeof *hc);
603                 if (!hc)
604                         WARNING("allocation failed");
605                 else {
606                         hc->export = export;
607                         hc->callback = callback;
608                         hc->cbclosure = cbclosure;
609                         callback = svc_hooked_call_result;
610                         cbclosure = hc;
611                 }
612         }
613         svc_call(closure, api, verb, args, callback, cbclosure);
614 }
615
616 static int svc_hooked_call_sync(void *closure, const char *api, const char *verb, struct json_object *args,
617                                 struct json_object **result)
618 {
619         struct afb_export *export = closure;
620         struct json_object *resu;
621         int rc;
622
623         if (export->hooksvc & afb_hook_flag_svc_callsync)
624                 afb_hook_svc_callsync(export, api, verb, args);
625
626         rc = svc_call_sync(closure, api, verb, args, &resu);
627
628         if (export->hooksvc & afb_hook_flag_svc_callsync_result)
629                 afb_hook_svc_callsync_result(export, rc, resu);
630
631         if (result)
632                 *result = resu;
633         else
634                 json_object_put(resu);
635
636         return rc;
637 }
638
639 /* the interface for services */
640 static const struct afb_service_itf service_itf = {
641         .call = svc_call,
642         .call_sync = svc_call_sync
643 };
644
645 /* the interface for services */
646 static const struct afb_service_itf hooked_service_itf = {
647         .call = svc_hooked_call,
648         .call_sync = svc_hooked_call_sync
649 };
650
651 /*************************************************************************************************************
652  *************************************************************************************************************
653  *************************************************************************************************************
654  *************************************************************************************************************
655                                            F R O M     S V C
656  *************************************************************************************************************
657  *************************************************************************************************************
658  *************************************************************************************************************
659  *************************************************************************************************************/
660
661 /*
662  * Propagates the event to the service
663  */
664 static void export_on_event_v12(void *closure, const char *event, int eventid, struct json_object *object)
665 {
666         struct afb_export *export = closure;
667
668         if (export->hooksvc & afb_hook_flag_svc_on_event_before)
669                 afb_hook_svc_on_event_before(export, event, eventid, object);
670         export->on_event.v12(event, object);
671         if (export->hooksvc & afb_hook_flag_svc_on_event_after)
672                 afb_hook_svc_on_event_after(export, event, eventid, object);
673         json_object_put(object);
674 }
675
676 /* the interface for events */
677 static const struct afb_evt_itf evt_v12_itf = {
678         .broadcast = export_on_event_v12,
679         .push = export_on_event_v12
680 };
681
682 /*************************************************************************************************************
683  *************************************************************************************************************
684  *************************************************************************************************************
685  *************************************************************************************************************
686                                            M E R G E D
687  *************************************************************************************************************
688  *************************************************************************************************************
689  *************************************************************************************************************
690  *************************************************************************************************************/
691
692 static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
693 {
694         struct afb_export *export;
695
696         /* session shared with other exports */
697         if (common_session == NULL) {
698                 common_session = afb_session_create (NULL, 0);
699                 if (common_session == NULL)
700                         return NULL;
701         }
702         export = calloc(1, sizeof *export);
703         if (!export)
704                 errno = ENOMEM;
705         else {
706                 memset(export, 0, sizeof *export);
707                 export->apiname = strdup(apiname);
708                 export->version = version;
709                 export->state = Api_State_Pre_Init;
710                 export->session = afb_session_addref(common_session);
711                 export->apiset = afb_apiset_addref(apiset);
712         }
713         return export;
714 }
715
716 void afb_export_destroy(struct afb_export *export)
717 {
718         if (export) {
719                 if (export->listener != NULL)
720                         afb_evt_listener_unref(export->listener);
721                 afb_session_unref(export->session);
722                 afb_apiset_unref(export->apiset);
723                 free(export->apiname);
724                 free(export);
725         }
726 }
727
728 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*))
729 {
730         struct afb_export *export = create(apiset, apiname, Api_Version_1);
731         if (export) {
732                 export->init.v1 = init;
733                 export->on_event.v12 = onevent;
734                 export->export.v1.verbosity = verbosity;
735                 export->export.v1.mode = AFB_MODE_LOCAL;
736                 export->export.v1.daemon.closure = export;
737                 afb_export_update_hook(export);
738         }
739         return export;
740 }
741
742 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*))
743 {
744         struct afb_export *export = create(apiset, apiname, Api_Version_2);
745         if (export) {
746                 export->init.v2 = init;
747                 export->on_event.v12 = onevent;
748                 export->export.v2 = data;
749                 data->verbosity = verbosity;
750                 data->daemon.closure = export;
751                 data->service.closure = export;
752                 afb_export_update_hook(export);
753         }
754         return export;
755 }
756
757 void afb_export_rename(struct afb_export *export, const char *apiname)
758 {
759         free(export->apiname);
760         export->apiname = strdup(apiname);
761         afb_export_update_hook(export);
762 }
763
764 const char *afb_export_apiname(const struct afb_export *export)
765 {
766         return export->apiname;
767 }
768
769 void afb_export_update_hook(struct afb_export *export)
770 {
771         export->hookditf = afb_hook_flags_ditf(export->apiname);
772         export->hooksvc = afb_hook_flags_svc(export->apiname);
773         switch (export->version) {
774         case Api_Version_1:
775                 export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
776                 break;
777         default:
778         case Api_Version_2:
779                 export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf;
780                 export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf;
781                 break;
782         }
783 }
784
785 struct afb_binding_interface_v1 *afb_export_get_interface_v1(struct afb_export *export)
786 {
787         return export->version == Api_Version_1 ? &export->export.v1 : NULL;
788 }
789
790 int afb_export_unshare_session(struct afb_export *export)
791 {
792         if (export->session == common_session) {
793                 export->session = afb_session_create (NULL, 0);
794                 if (export->session)
795                         afb_session_unref(common_session);
796                 else {
797                         export->session = common_session;
798                         return -1;
799                 }
800         }
801         return 0;
802 }
803
804 void afb_export_set_apiset(struct afb_export *export, struct afb_apiset *apiset)
805 {
806         struct afb_apiset *prvset = export->apiset;
807         export->apiset = afb_apiset_addref(apiset);
808         afb_apiset_unref(prvset);
809 }
810
811 struct afb_apiset *afb_export_get_apiset(struct afb_export *export)
812 {
813         return export->apiset;
814 }
815
816 /*
817  * Creates a new service
818  */
819 int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
820 {
821         /* check version */
822         switch (export->version) {
823         case Api_Version_1: case Api_Version_2: break;
824         default:
825                 ERROR("invalid version 12 for API %s", export->apiname);
826                 errno = EINVAL;
827                 return -1;
828         }
829
830         /* set the event handler */
831         if (!on_event) {
832                 if (export->listener) {
833                         afb_evt_listener_unref(export->listener);
834                         export->listener = NULL;
835                 }
836                 export->on_event.v12 = on_event;
837         } else {
838                 export->on_event.v12 = on_event;
839                 if (!export->listener) {
840                         export->listener = afb_evt_listener_create(&evt_v12_itf, export);
841                         if (export->listener == NULL)
842                                 return -1;
843                 }
844         }
845         return 0;
846 }
847
848 /*
849  * Starts a new service (v1)
850  */
851 struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct afb_binding_v1 *(*regfun)(const struct afb_binding_interface_v1*))
852 {
853         return regfun(&export->export.v1);
854 }
855
856 int afb_export_verbosity_get(const struct afb_export *export)
857 {
858         switch (export->version) {
859         case Api_Version_1: return export->export.v1.verbosity;
860         case Api_Version_2: return export->export.v2->verbosity;
861         }
862         return verbosity;
863 }
864
865 void afb_export_verbosity_set(struct afb_export *export, int level)
866 {
867         switch (export->version) {
868         case Api_Version_1: export->export.v1.verbosity = level; break;
869         case Api_Version_2: export->export.v2->verbosity = level; break;
870         }
871 }
872
873 /*************************************************************************************************************
874  *************************************************************************************************************
875  *************************************************************************************************************
876  *************************************************************************************************************
877                                            N E W
878  *************************************************************************************************************
879  *************************************************************************************************************
880  *************************************************************************************************************
881  *************************************************************************************************************/
882
883 int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
884 {
885         int rc;
886
887         /* check state */
888         if (export->state != Api_State_Pre_Init) {
889                 /* not an error when onneed */
890                 if (onneed != 0)
891                         goto done;
892
893                 /* already started: it is an error */
894                 ERROR("Service of API %s already started", export->apiname);
895                 return -1;
896         }
897
898         /* unshare the session if asked */
899         if (!share_session) {
900                 rc = afb_export_unshare_session(export);
901                 if (rc < 0) {
902                         ERROR("Can't unshare the session for %s", export->apiname);
903                         return -1;
904                 }
905         }
906
907         /* set event handling */
908         switch (export->version) {
909         case Api_Version_1:
910         case Api_Version_2:
911                 rc = afb_export_handle_events_v12(export, export->on_event.v12);
912                 break;
913         default:
914                 rc = 0;
915                 break;
916         }
917         if (rc < 0) {
918                 ERROR("Can't set event handler for %s", export->apiname);
919                 return -1;
920         }
921
922         /* Starts the service */
923         if (export->hooksvc & afb_hook_flag_svc_start_before)
924                 afb_hook_svc_start_before(export);
925         export->state = Api_State_Init;
926         switch (export->version) {
927         case Api_Version_1:
928                 rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
929                 break;
930         case Api_Version_2:
931                 rc = export->init.v2 ? export->init.v2() : 0;
932                 break;
933         default:
934                 break;
935         }
936         export->state = Api_State_Run;
937         if (export->hooksvc & afb_hook_flag_svc_start_after)
938                 afb_hook_svc_start_after(export, rc);
939         if (rc < 0) {
940                 /* initialisation error */
941                 ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);
942                 return rc;
943         }
944
945 done:
946         return 0;
947 }
948