#include "jobs.h"
#include "verbose.h"
-extern struct afb_apiset *main_apiset;
/*************************************************************************
* internal types and structures
/* event listener for service or NULL */
struct afb_evt_listener *listener;
- /* event callback for service */
- void (*on_event)(const char *event, struct json_object *object);
+ /* start function */
+ union {
+ int (*v1)(struct afb_service);
+ int (*v2)();
+ } init;
+
+ /* event handling */
+ union {
+ void (*v12)(const char *event, struct json_object *object);
+ } on_event;
/* exported data */
union {
size_t plen, nlen;
char *event;
struct afb_export *export = closure;
+ struct afb_eventid *eventid;
/* check daemon state */
if (export->state == Api_State_Pre_Init) {
memcpy(event + plen + 1, name, nlen + 1);
/* create the event */
- return afb_evt_create_event(event);
+ eventid = afb_evt_create_event(event);
+ return (struct afb_event){ .itf = eventid ? eventid->itf : NULL, .closure = eventid };
}
static int event_broadcast_cb(void *closure, const char *name, struct json_object *object)
errno = EINVAL;
return -1;
}
- return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(main_apiset, name, 1);
+ return -!(initialized ? afb_apiset_lookup_started : afb_apiset_lookup)(export->apiset, name, 1);
}
static int rename_api_cb(void *closure, const char *name)
{
struct afb_export *export = closure;
struct afb_event r = event_make_cb(closure, name);
- return afb_hook_ditf_event_make(export, name, r);
+ afb_hook_ditf_event_make(export, name, r.closure);
+ return r;
}
static int hooked_event_broadcast_cb(void *closure, const char *name, struct json_object *object)
struct jobloop *jobloop;
struct json_object *result;
int status;
- int async;
};
/*
callreq->jobloop = NULL;
callreq->callback = callback;
callreq->closure = cbclosure;
- callreq->async = 1;
/* terminates and frees ressources if needed */
afb_xreq_process(&callreq->xreq, export->apiset);
callreq->callback = NULL;
callreq->result = NULL;
callreq->status = 0;
- callreq->async = 0;
afb_xreq_unhooked_addref(&callreq->xreq); /* avoid early callreq destruction */
rc = jobs_enter(NULL, 0, callreq_sync_enter, callreq);
if (rc >= 0)
/*
* Propagates the event to the service
*/
-static void export_on_event(void *closure, const char *event, int eventid, struct json_object *object)
+static void export_on_event_v12(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(event, object);
+ export->on_event.v12(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_itf = {
- .broadcast = export_on_event,
- .push = export_on_event
+static const struct afb_evt_itf evt_v12_itf = {
+ .broadcast = export_on_event_v12,
+ .push = export_on_event_v12
};
/*************************************************************************************************************
*************************************************************************************************************
*************************************************************************************************************/
-static struct afb_export *create(const char *apiname, enum afb_api_version version)
+static struct afb_export *create(struct afb_apiset *apiset, const char *apiname, enum afb_api_version version)
{
struct afb_export *export;
export->version = version;
export->state = Api_State_Pre_Init;
export->session = afb_session_addref(common_session);
- export->apiset = afb_apiset_addref(main_apiset);
+ export->apiset = afb_apiset_addref(apiset);
}
return export;
}
}
}
-struct afb_export *afb_export_create_v1(const char *apiname)
+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*))
{
- struct afb_export *export = create(apiname, Api_Version_1);
+ struct afb_export *export = create(apiset, apiname, Api_Version_1);
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;
return export;
}
-struct afb_export *afb_export_create_v2(const char *apiname, struct afb_binding_data_v2 *data)
+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*))
{
- struct afb_export *export = create(apiname, Api_Version_2);
+ struct afb_export *export = create(apiset, apiname, Api_Version_2);
if (export) {
+ 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_update_hook(export);
/*
* Creates a new service
*/
-int afb_export_handle_events(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
+int afb_export_handle_events_v12(struct afb_export *export, void (*on_event)(const char *event, struct json_object *object))
{
- if (on_event != export->on_event) {
- if (!on_event) {
+ /* check version */
+ switch (export->version) {
+ case Api_Version_1: case Api_Version_2: break;
+ default:
+ ERROR("invalid version 12 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;
- } else if (!export->listener) {
- export->listener = afb_evt_listener_create(&evt_itf, export);
+ }
+ export->on_event.v12 = on_event;
+ } else {
+ export->on_event.v12 = on_event;
+ if (!export->listener) {
+ export->listener = afb_evt_listener_create(&evt_v12_itf, export);
if (export->listener == NULL)
return -1;
}
- export->on_event = on_event;
}
return 0;
}
-
-
-int afb_export_is_started(const struct afb_export *export)
-{
- return export->state != Api_State_Pre_Init;
-}
-
-
/*
* Starts a new service (v1)
*/
return regfun(&export->export.v1);
}
-int afb_export_start_v1(struct afb_export *export, int (*start)(struct afb_service))
-{
- int rc;
- struct afb_service svc = { .itf = &hooked_service_itf, .closure = export };
-
- if (export->hooksvc & afb_hook_flag_svc_start_before)
- afb_hook_svc_start_before(export);
- export->state = Api_State_Init;
- rc = start ? start(svc) : 0;
- export->state = Api_State_Run;
- if (export->hooksvc & afb_hook_flag_svc_start_after)
- afb_hook_svc_start_after(export, rc);
- return rc;
-}
-
-/*
- * Starts a new service (v2)
- */
-int afb_export_start_v2(struct afb_export *export, int (*start)())
-{
- int rc;
-
- if (export->hooksvc & afb_hook_flag_svc_start_before)
- afb_hook_svc_start_before(export);
- export->state = Api_State_Init;
- rc = start ? start() : 0;
- export->state = Api_State_Run;
- if (export->hooksvc & afb_hook_flag_svc_start_after)
- afb_hook_svc_start_after(export, rc);
- if (rc >= 0)
- export->state = Api_State_Run;
- return rc;
-}
-
int afb_export_verbosity_get(const struct afb_export *export)
{
switch (export->version) {
}
}
+/*************************************************************************************************************
+ *************************************************************************************************************
+ *************************************************************************************************************
+ *************************************************************************************************************
+ N E W
+ *************************************************************************************************************
+ *************************************************************************************************************
+ *************************************************************************************************************
+ *************************************************************************************************************/
+
+int afb_export_start(struct afb_export *export, int share_session, int onneed, struct afb_apiset *apiset)
+{
+ int rc;
+
+ /* check state */
+ if (export->state != Api_State_Pre_Init) {
+ /* not an error when onneed */
+ if (onneed != 0)
+ goto done;
+
+ /* already started: it is an error */
+ ERROR("Service of API %s already started", export->apiname);
+ return -1;
+ }
+
+ /* unshare the session if asked */
+ if (!share_session) {
+ rc = afb_export_unshare_session(export);
+ if (rc < 0) {
+ ERROR("Can't unshare the session for %s", export->apiname);
+ return -1;
+ }
+ }
+
+ /* set event handling */
+ switch (export->version) {
+ case Api_Version_1:
+ case Api_Version_2:
+ rc = afb_export_handle_events_v12(export, export->on_event.v12);
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+ if (rc < 0) {
+ ERROR("Can't set event handler for %s", export->apiname);
+ return -1;
+ }
+
+ /* Starts the service */
+ if (export->hooksvc & afb_hook_flag_svc_start_before)
+ afb_hook_svc_start_before(export);
+ export->state = Api_State_Init;
+ switch (export->version) {
+ case Api_Version_1:
+ rc = export->init.v1 ? export->init.v1((struct afb_service){ .itf = &hooked_service_itf, .closure = export }) : 0;
+ break;
+ case Api_Version_2:
+ rc = export->init.v2 ? export->init.v2() : 0;
+ break;
+ default:
+ break;
+ }
+ export->state = Api_State_Run;
+ if (export->hooksvc & afb_hook_flag_svc_start_after)
+ afb_hook_svc_start_after(export, rc);
+ if (rc < 0) {
+ /* initialisation error */
+ ERROR("Initialisation of service API %s failed (%d): %m", export->apiname, rc);
+ return rc;
+ }
+
+done:
+ return 0;
+}
+