X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-export.c;h=5688cfee44f6cbc9e848d765c76b883bfab7e0aa;hb=59cd34b59853f6a47e756d7ab5bc0329f40a471c;hp=bd5b61e0794fc4e3fb2db479e500da2685c22c86;hpb=325e6a7f034c80562096d60ab01f2e4532eea98c;p=src%2Fapp-framework-binder.git diff --git a/src/afb-export.c b/src/afb-export.c index bd5b61e0..5688cfee 100644 --- a/src/afb-export.c +++ b/src/afb-export.c @@ -23,11 +23,12 @@ #include -#include -#include +#define AFB_BINDING_VERSION 0 +#include #include "afb-api.h" #include "afb-apiset.h" +#include "afb-api-dyn.h" #include "afb-common.h" #include "afb-cred.h" #include "afb-evt.h" @@ -39,17 +40,15 @@ #include "jobs.h" #include "verbose.h" - /************************************************************************* * internal types and structures ************************************************************************/ enum afb_api_version { - Api_Version_None = 0, + Api_Version_Dyn = 0, Api_Version_1 = 1, Api_Version_2 = 2, - Api_Version_3 = 3 }; enum afb_api_state @@ -61,6 +60,9 @@ enum afb_api_state struct afb_export { + /* keep it first */ + struct afb_dynapi dynapi; + /* name of the api */ char *apiname; @@ -74,6 +76,9 @@ struct afb_export int hookditf; int hooksvc; + /* dynamic api */ + struct afb_api_dyn *apidyn; + /* session for service */ struct afb_session *session; @@ -87,11 +92,13 @@ struct afb_export union { int (*v1)(struct afb_service); int (*v2)(); + int (*vdyn)(struct afb_dynapi *dynapi); } init; /* event handling */ union { void (*v12)(const char *event, struct json_object *object); + void (*vdyn)(struct afb_dynapi *dynapi, const char *event, struct json_object *object); } on_event; /* exported data */ @@ -101,6 +108,18 @@ struct afb_export } export; }; +/************************************************************************************************************/ + +static inline struct afb_dynapi *to_dynapi(struct afb_export *export) +{ + return (struct afb_dynapi*)export; +} + +static inline struct afb_export *from_dynapi(struct afb_dynapi *dynapi) +{ + return (struct afb_export*)dynapi; +} + /************************************************************************************************************* ************************************************************************************************************* ************************************************************************************************************* @@ -232,6 +251,17 @@ static int rename_api_cb(void *closure, const char *name) return 0; } +static int api_new_api_cb( + void *closure, + const char *api, + const char *info, + int (*preinit)(void*, struct afb_dynapi *), + void *preinit_closure) +{ + struct afb_export *export = closure; + return afb_api_dyn_add(export->apiset, api, info, preinit, preinit_closure); +} + /********************************************** * hooked flow **********************************************/ @@ -342,6 +372,16 @@ static int hooked_rename_api_cb(void *closure, const char *name) return afb_hook_ditf_rename_api(export, oldname, name, result); } +static int hooked_api_new_api_cb( + void *closure, + const char *api, + const char *info, + int (*preinit)(void*, struct afb_dynapi *), + void *preinit_closure) +{ + /* TODO */ + return api_new_api_cb(closure, api, info, preinit, preinit_closure); +} /********************************************** * vectors **********************************************/ @@ -358,7 +398,8 @@ static const struct afb_daemon_itf daemon_itf = { .queue_job = queue_job_cb, .unstore_req = unstore_req_cb, .require_api = require_api_cb, - .rename_api = rename_api_cb + .rename_api = rename_api_cb, + .new_api = api_new_api_cb, }; static const struct afb_daemon_itf hooked_daemon_itf = { @@ -374,10 +415,10 @@ static const struct afb_daemon_itf hooked_daemon_itf = { .queue_job = hooked_queue_job_cb, .unstore_req = hooked_unstore_req_cb, .require_api = hooked_require_api_cb, - .rename_api = hooked_rename_api_cb + .rename_api = hooked_rename_api_cb, + .new_api = hooked_api_new_api_cb, }; - /************************************************************************************************************* ************************************************************************************************************* ************************************************************************************************************* @@ -411,7 +452,10 @@ struct call_req struct afb_export *export; /* the args */ - void (*callback)(void*, int, struct json_object*); + union { + void (*callback)(void*, int, struct json_object*); + void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*); + }; void *closure; /* sync */ @@ -433,7 +477,7 @@ static void callreq_destroy(struct afb_xreq *xreq) free(callreq); } -static void callreq_reply(struct afb_xreq *xreq, int status, json_object *obj) +static void callreq_reply_async(struct afb_xreq *xreq, int status, json_object *obj) { struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq); if (callreq->callback) @@ -441,6 +485,14 @@ static void callreq_reply(struct afb_xreq *xreq, int status, json_object *obj) json_object_put(obj); } +static void callreq_reply_async_dynapi(struct afb_xreq *xreq, int status, json_object *obj) +{ + struct call_req *callreq = CONTAINER_OF_XREQ(struct call_req, xreq); + if (callreq->callback_dynapi) + callreq->callback_dynapi(callreq->closure, status, obj, to_dynapi(callreq->export)); + json_object_put(obj); +} + static void callreq_sync_leave(struct call_req *callreq) { struct jobloop *jobloop = callreq->jobloop; @@ -474,9 +526,15 @@ static void callreq_sync_enter(int signum, void *closure, struct jobloop *jobloo } /* interface for requests of services */ -const struct afb_xreq_query_itf afb_export_xreq_itf = { +const struct afb_xreq_query_itf afb_export_xreq_async_itf = { .unref = callreq_destroy, - .reply = callreq_reply + .reply = callreq_reply_async +}; + +/* interface for requests of services */ +const struct afb_xreq_query_itf afb_export_xreq_async_dynapi_itf = { + .unref = callreq_destroy, + .reply = callreq_reply_async_dynapi }; /* interface for requests of services */ @@ -488,7 +546,12 @@ const struct afb_xreq_query_itf afb_export_xreq_sync_itf = { /* * create an call_req */ -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) +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) { struct call_req *callreq; size_t lenapi, lenverb; @@ -519,14 +582,20 @@ static struct call_req *callreq_create(struct afb_export *export, const char *ap /* * Initiates a call for the service */ -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) +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) { struct afb_export *export = closure; struct call_req *callreq; struct json_object *ierr; /* allocates the request */ - callreq = callreq_create(export, api, verb, args, &afb_export_xreq_itf); + callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_itf); if (callreq == NULL) { ERROR("out of memory"); json_object_put(args); @@ -546,8 +615,45 @@ static void svc_call(void *closure, const char *api, const char *verb, struct js afb_xreq_process(&callreq->xreq, export->apiset); } -static int svc_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, - struct json_object **result) +static void svc_call_dynapi( + struct afb_dynapi *dynapi, + const char *api, + const char *verb, + struct json_object *args, + void (*callback)(void*, int, struct json_object*, struct afb_dynapi*), + void *cbclosure) +{ + struct afb_export *export = from_dynapi(dynapi); + struct call_req *callreq; + struct json_object *ierr; + + /* allocates the request */ + callreq = callreq_create(export, api, verb, args, &afb_export_xreq_async_dynapi_itf); + if (callreq == NULL) { + ERROR("out of memory"); + json_object_put(args); + ierr = afb_msg_json_internal_error(); + if (callback) + callback(cbclosure, -1, ierr, to_dynapi(export)); + json_object_put(ierr); + return; + } + + /* initialises the request */ + callreq->jobloop = NULL; + callreq->callback_dynapi = callback; + callreq->closure = cbclosure; + + /* terminates and frees ressources if needed */ + afb_xreq_process(&callreq->xreq, export->apiset); +} + +static int svc_call_sync( + void *closure, + const char *api, + const char *verb, + struct json_object *args, + struct json_object **result) { struct afb_export *export = closure; struct call_req *callreq; @@ -585,7 +691,10 @@ static int svc_call_sync(void *closure, const char *api, const char *verb, struc struct hooked_call { struct afb_export *export; - void (*callback)(void*, int, struct json_object*); + union { + void (*callback)(void*, int, struct json_object*); + void (*callback_dynapi)(void*, int, struct json_object*, struct afb_dynapi*); + }; void *cbclosure; }; @@ -597,7 +706,21 @@ static void svc_hooked_call_result(void *closure, int status, struct json_object free(hc); } -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) +static void svc_hooked_call_dynapi_result(void *closure, int status, struct json_object *result, struct afb_dynapi *dynapi) +{ + struct hooked_call *hc = closure; + afb_hook_svc_call_result(hc->export, status, result); + hc->callback_dynapi(hc->cbclosure, status, result, dynapi); + free(hc); +} + +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) { struct afb_export *export = closure; struct hooked_call *hc; @@ -620,8 +743,41 @@ static void svc_hooked_call(void *closure, const char *api, const char *verb, st svc_call(closure, api, verb, args, callback, cbclosure); } -static int svc_hooked_call_sync(void *closure, const char *api, const char *verb, struct json_object *args, - struct json_object **result) +static void svc_hooked_call_dynapi( + struct afb_dynapi *dynapi, + const char *api, + const char *verb, + struct json_object *args, + void (*callback)(void*, int, struct json_object*, struct afb_dynapi*), + void *cbclosure) +{ + struct afb_export *export = from_dynapi(dynapi); + struct hooked_call *hc; + + if (export->hooksvc & afb_hook_flag_svc_call) + afb_hook_svc_call(export, api, verb, args); + + if (export->hooksvc & afb_hook_flag_svc_call_result) { + hc = malloc(sizeof *hc); + if (!hc) + WARNING("allocation failed"); + else { + hc->export = export; + hc->callback_dynapi = callback; + hc->cbclosure = cbclosure; + callback = svc_hooked_call_dynapi_result; + cbclosure = hc; + } + } + svc_call_dynapi(dynapi, api, verb, args, callback, cbclosure); +} + +static int svc_hooked_call_sync( + void *closure, + const char *api, + const char *verb, + struct json_object *args, + struct json_object **result) { struct afb_export *export = closure; struct json_object *resu; @@ -655,6 +811,195 @@ static const struct afb_service_itf hooked_service_itf = { .call_sync = svc_hooked_call_sync }; +/************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + F R O M D Y N A P I + ************************************************************************************************************* + ************************************************************************************************************* + ************************************************************************************************************* + *************************************************************************************************************/ + +static int api_set_verbs_v2_cb( + struct afb_dynapi *dynapi, + const struct afb_verb_v2 *verbs) +{ + struct afb_export *export = from_dynapi(dynapi); + + if (export->apidyn) { + afb_api_dyn_set_verbs_v2(export->apidyn, verbs); + return 0; + } + + errno = EPERM; + return -1; +} + +static int api_add_verb_cb( + struct afb_dynapi *dynapi, + const char *verb, + const char *info, + void (*callback)(struct afb_request *request), + const struct afb_auth *auth, + uint32_t session) +{ + struct afb_export *export = from_dynapi(dynapi); + + if (export->apidyn) + return afb_api_dyn_add_verb(export->apidyn, verb, info, callback, auth, session); + + errno = EPERM; + return -1; +} + +static int api_sub_verb_cb( + struct afb_dynapi *dynapi, + const char *verb) +{ + struct afb_export *export = from_dynapi(dynapi); + + if (export->apidyn) + return afb_api_dyn_sub_verb(export->apidyn, verb); + + errno = EPERM; + return -1; +} + +static int api_set_on_event_cb( + struct afb_dynapi *dynapi, + void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object)) +{ + struct afb_export *export = from_dynapi(dynapi); + return afb_export_handle_events_vdyn(export, onevent); +} + +static int api_set_on_init_cb( + struct afb_dynapi *dynapi, + int (*oninit)(struct afb_dynapi *dynapi)) +{ + struct afb_export *export = from_dynapi(dynapi); + + return afb_export_handle_init_vdyn(export, oninit); +} + +static void api_seal_cb( + struct afb_dynapi *dynapi) +{ + struct afb_export *export = from_dynapi(dynapi); + + export->apidyn = NULL; +} + +static int hooked_api_set_verbs_v2_cb( + struct afb_dynapi *dynapi, + const struct afb_verb_v2 *verbs) +{ + /* TODO */ + return api_set_verbs_v2_cb(dynapi, verbs); +} + +static int hooked_api_add_verb_cb( + struct afb_dynapi *dynapi, + const char *verb, + const char *info, + void (*callback)(struct afb_request *request), + const struct afb_auth *auth, + uint32_t session) +{ + /* TODO */ + return api_add_verb_cb(dynapi, verb, info, callback, auth, session); +} + +static int hooked_api_sub_verb_cb( + struct afb_dynapi *dynapi, + const char *verb) +{ + /* TODO */ + return api_sub_verb_cb(dynapi, verb); +} + +static int hooked_api_set_on_event_cb( + struct afb_dynapi *dynapi, + void (*onevent)(struct afb_dynapi *dynapi, const char *event, struct json_object *object)) +{ + /* TODO */ + return api_set_on_event_cb(dynapi, onevent); +} + +static int hooked_api_set_on_init_cb( + struct afb_dynapi *dynapi, + int (*oninit)(struct afb_dynapi *dynapi)) +{ + /* TODO */ + return api_set_on_init_cb(dynapi, oninit); +} + +static void hooked_api_seal_cb( + struct afb_dynapi *dynapi) +{ + /* TODO */ + api_seal_cb(dynapi); +} + +static const struct afb_dynapi_itf dynapi_itf = { + + .vverbose = (void*)vverbose_cb, + + .get_event_loop = afb_common_get_event_loop, + .get_user_bus = afb_common_get_user_bus, + .get_system_bus = afb_common_get_system_bus, + .rootdir_get_fd = afb_common_rootdir_get_fd, + .rootdir_open_locale = rootdir_open_locale_cb, + .queue_job = queue_job_cb, + + .require_api = require_api_cb, + .rename_api = rename_api_cb, + + .event_broadcast = event_broadcast_cb, + .eventid_make = eventid_make_cb, + + .call = svc_call_dynapi, + .call_sync = svc_call_sync, + + .api_new_api = api_new_api_cb, + .api_set_verbs_v2 = api_set_verbs_v2_cb, + .api_add_verb = api_add_verb_cb, + .api_sub_verb = api_sub_verb_cb, + .api_set_on_event = api_set_on_event_cb, + .api_set_on_init = api_set_on_init_cb, + .api_seal = api_seal_cb, +}; + +static const struct afb_dynapi_itf hooked_dynapi_itf = { + + .vverbose = hooked_vverbose_cb, + + .get_event_loop = hooked_get_event_loop, + .get_user_bus = hooked_get_user_bus, + .get_system_bus = hooked_get_system_bus, + .rootdir_get_fd = hooked_rootdir_get_fd, + .rootdir_open_locale = hooked_rootdir_open_locale_cb, + .queue_job = hooked_queue_job_cb, + + .require_api = hooked_require_api_cb, + .rename_api = hooked_rename_api_cb, + + .event_broadcast = hooked_event_broadcast_cb, + .eventid_make = hooked_eventid_make_cb, + + .call = svc_hooked_call_dynapi, + .call_sync = svc_hooked_call_sync, + + .api_new_api = hooked_api_new_api_cb, + .api_set_verbs_v2 = hooked_api_set_verbs_v2_cb, + .api_add_verb = hooked_api_add_verb_cb, + .api_sub_verb = hooked_api_sub_verb_cb, + .api_set_on_event = hooked_api_set_on_event_cb, + .api_set_on_init = hooked_api_set_on_init_cb, + .api_seal = hooked_api_seal_cb, +}; + /************************************************************************************************************* ************************************************************************************************************* ************************************************************************************************************* @@ -686,6 +1031,27 @@ static const struct afb_evt_itf evt_v12_itf = { .push = export_on_event_v12 }; +/* + * Propagates the event to the service + */ +static void export_on_event_vdyn(void *closure, const char *event, int eventid, struct json_object *object) +{ + struct afb_export *export = closure; + + if (export->hooksvc & afb_hook_flag_svc_on_event_before) + afb_hook_svc_on_event_before(export, event, eventid, object); + export->on_event.vdyn(to_dynapi(export), event, object); + if (export->hooksvc & afb_hook_flag_svc_on_event_after) + afb_hook_svc_on_event_after(export, event, eventid, object); + json_object_put(object); +} + +/* the interface for events */ +static const struct afb_evt_itf evt_vdyn_itf = { + .broadcast = export_on_event_vdyn, + .push = export_on_event_vdyn +}; + /************************************************************************************************************* ************************************************************************************************************* ************************************************************************************************************* @@ -738,9 +1104,9 @@ struct afb_export *afb_export_create_v1(struct afb_apiset *apiset, const char *a if (export) { export->init.v1 = init; export->on_event.v12 = onevent; - export->export.v1.verbosity = verbosity; export->export.v1.mode = AFB_MODE_LOCAL; export->export.v1.daemon.closure = export; + afb_export_verbosity_set(export, verbosity); afb_export_update_hook(export); } return export; @@ -753,9 +1119,20 @@ struct afb_export *afb_export_create_v2(struct afb_apiset *apiset, const char *a export->init.v2 = init; export->on_event.v12 = onevent; export->export.v2 = data; - data->verbosity = verbosity; data->daemon.closure = export; data->service.closure = export; + afb_export_verbosity_set(export, verbosity); + afb_export_update_hook(export); + } + return export; +} + +struct afb_export *afb_export_create_vdyn(struct afb_apiset *apiset, const char *apiname, struct afb_api_dyn *apidyn) +{ + struct afb_export *export = create(apiset, apiname, Api_Version_Dyn); + if (export) { + export->apidyn = apidyn; + afb_export_verbosity_set(export, verbosity); afb_export_update_hook(export); } return export; @@ -777,11 +1154,12 @@ void afb_export_update_hook(struct afb_export *export) { export->hookditf = afb_hook_flags_ditf(export->apiname); export->hooksvc = afb_hook_flags_svc(export->apiname); + export->dynapi.itf = export->hookditf|export->hooksvc ? &hooked_dynapi_itf : &dynapi_itf; + switch (export->version) { case Api_Version_1: export->export.v1.daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf; break; - default: case Api_Version_2: export->export.v2->daemon.itf = export->hookditf ? &hooked_daemon_itf : &daemon_itf; export->export.v2->service.itf = export->hooksvc ? &hooked_service_itf : &service_itf; @@ -820,9 +1198,6 @@ struct afb_apiset *afb_export_get_apiset(struct afb_export *export) return export->apiset; } -/* - * Creates a new service - */ int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object)) { /* check version */ @@ -852,6 +1227,47 @@ int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(con return 0; } +int afb_export_handle_events_vdyn(struct afb_export *export, void (*on_event)(struct afb_dynapi *dynapi, const char *event, struct json_object *object)) +{ + /* check version */ + switch (export->version) { + case Api_Version_Dyn: break; + default: + ERROR("invalid version Dyn for API %s", export->apiname); + errno = EINVAL; + return -1; + } + + /* set the event handler */ + if (!on_event) { + if (export->listener) { + afb_evt_listener_unref(export->listener); + export->listener = NULL; + } + export->on_event.vdyn = on_event; + } else { + export->on_event.vdyn = on_event; + if (!export->listener) { + export->listener = afb_evt_listener_create(&evt_vdyn_itf, export); + if (export->listener == NULL) + return -1; + } + } + return 0; +} + +int afb_export_handle_init_vdyn(struct afb_export *export, int (*oninit)(struct afb_dynapi *dynapi)) +{ + if (export->state != Api_State_Pre_Init) { + ERROR("[API %s] Bad call to 'afb_dynapi_on_init', must be in PreInit", export->apiname); + errno = EINVAL; + return -1; + } + + export->init.vdyn = oninit; + return 0; +} + /* * Starts a new service (v1) */ @@ -860,17 +1276,19 @@ struct afb_binding_v1 *afb_export_register_v1(struct afb_export *export, struct return regfun(&export->export.v1); } +int afb_export_preinit_vdyn(struct afb_export *export, int (*preinit)(void*, struct afb_dynapi*), void *closure) +{ + return preinit(closure, to_dynapi(export)); +} + int afb_export_verbosity_get(const struct afb_export *export) { - switch (export->version) { - case Api_Version_1: return export->export.v1.verbosity; - case Api_Version_2: return export->export.v2->verbosity; - } - return verbosity; + return export->dynapi.verbosity; } void afb_export_verbosity_set(struct afb_export *export, int level) { + export->dynapi.verbosity = level; switch (export->version) { case Api_Version_1: export->export.v1.verbosity = level; break; case Api_Version_2: export->export.v2->verbosity = level; break; @@ -937,6 +1355,9 @@ int afb_export_start(struct afb_export *export, int share_session, int onneed, s case Api_Version_2: rc = export->init.v2 ? export->init.v2() : 0; break; + case Api_Version_Dyn: + rc = export->init.vdyn ? export->init.vdyn(to_dynapi(export)) : 0; + break; default: break; }