+static void pingSample2 (struct afb_req_x1 req)
+{
+ pingSample(req.closure);
+}
+
+static const struct afb_verb_v2 apiverbs2[]= {
+ { .verb="ping", .callback=pingSample2 },
+ { .verb="ping2", .callback=pingSample2 },
+ { .verb=NULL }
+};
+
+static int apipreinit(void *closure, afb_api_t api)
+{
+ afb_api_set_verbs_v2(api, apiverbs2);
+ afb_api_set_verbs_v3(api, verbs);
+ return 0;
+}
+
+static void apiverb (afb_req_t request)
+{
+ afb_req_reply_f(request, json_object_get(afb_req_json(request)), NULL, "api: %s, verb: %s",
+ afb_req_get_called_api(request), afb_req_get_called_verb(request));
+}
+
+static void apievhndl(void *closure, const char *event, struct json_object *args, afb_api_t api)
+{
+ struct json_object *obj = closure;
+ afb_api_verbose(api, 0, NULL, 0, NULL, "the handler of closure(%s) received the event %s(%s)",
+ json_object_get_string(obj), event, json_object_get_string(args));
+}
+
+static void api (afb_req_t request)
+{
+ struct api *sapi, **psapi;
+ const char *action, *apiname, *verbname, *pattern;
+ json_object *json = afb_req_json(request), *x, *closure;
+ afb_api_t api = afb_req_get_api(request), oapi;
+
+ /* get the action */
+ if (!json_object_object_get_ex(json, "action", &x)) {
+ afb_req_reply(request, NULL, "invalid", "no action");
+ goto end;
+ }
+ action = json_object_get_string(x);
+
+ /* get the verb */
+ verbname = json_object_object_get_ex(json, "verb", &x) ?
+ json_object_get_string(x) : NULL;
+
+ /* get the pattern */
+ pattern = json_object_object_get_ex(json, "pattern", &x) ?
+ json_object_get_string(x) : NULL;
+
+ /* get the closure */
+ closure = NULL;
+ json_object_object_get_ex(json, "closure", &closure);
+
+ /* get the api */
+ if (json_object_object_get_ex(json, "api", &x)) {
+ apiname = json_object_get_string(x);
+ sapi = searchapi(apiname, &psapi);
+ oapi = sapi ? sapi->api : NULL;
+ } else {
+ oapi = api;
+ apiname = afb_api_name(api);
+ sapi = searchapi(apiname, &psapi);
+ }
+
+ /* search the sapi */
+ if (!strcasecmp(action, "create")) {
+ if (!apiname) {
+ afb_req_reply(request, NULL, "invalid", "no api");
+ goto end;
+ }
+ if (sapi) {
+ afb_req_reply(request, NULL, "already-exist", NULL);
+ goto end;
+ }
+ sapi = malloc (sizeof * sapi + strlen(apiname));
+ if (!sapi) {
+ afb_req_reply(request, NULL, "out-of-memory", NULL);
+ goto end;
+ }
+ sapi->api = afb_api_new_api(api, apiname, NULL, 1, apipreinit, NULL);
+ if (!sapi->api) {
+ afb_req_reply_f(request, NULL, "cant-create", "%m");
+ goto end;
+ }
+ strcpy(sapi->name, apiname);
+ sapi->next = NULL;
+ *psapi = sapi;
+ } else {
+ if (!oapi) {
+ afb_req_reply(request, NULL, "cant-find-api", NULL);
+ goto end;
+ }
+ if (!strcasecmp(action, "destroy")) {
+ if (!sapi) {
+ afb_req_reply(request, NULL, "cant-destroy", NULL);
+ goto end;
+ }
+ afb_api_delete_api(oapi);
+ *psapi = sapi->next;
+ free(sapi);
+ } else if (!strcasecmp(action, "addverb")) {
+ if (!verbname){
+ afb_req_reply(request, NULL, "invalid", "no verb");
+ goto end;
+ }
+ afb_api_add_verb(oapi, verbname, NULL, apiverb, NULL, NULL, 0, !!strchr(verbname, '*'));
+ } else if (!strcasecmp(action, "delverb")) {
+ if (!verbname){
+ afb_req_reply(request, NULL, "invalid", "no verb");
+ goto end;
+ }
+ afb_api_del_verb(oapi, verbname, NULL);
+ } else if (!strcasecmp(action, "addhandler")) {
+ if (!pattern){
+ afb_req_reply(request, NULL, "invalid", "no pattern");
+ goto end;
+ }
+ afb_api_event_handler_add(oapi, pattern, apievhndl, json_object_get(closure));
+ } else if (!strcasecmp(action, "delhandler")) {
+ if (!pattern){
+ afb_req_reply(request, NULL, "invalid", "no pattern");
+ goto end;
+ }
+ closure = NULL;
+ afb_api_event_handler_del(oapi, pattern, (void**)&closure);
+ json_object_put(closure);
+ } else if (!strcasecmp(action, "seal")) {
+ afb_api_seal(oapi);
+ } else {
+ afb_req_reply_f(request, NULL, "invalid", "unknown action %s", action ?: "NULL");
+ goto end;
+ }
+ }
+ afb_req_reply(request, NULL, NULL, NULL);
+end: return;
+}
+
+/*************************************************************/
+
+static int preinit(afb_api_t api)
+{
+ AFB_NOTICE("hello binding comes to live");
+#if defined(PREINIT_PROVIDE_CLASS)
+ afb_api_provide_class(api, PREINIT_PROVIDE_CLASS);
+#endif
+#if defined(PREINIT_REQUIRE_CLASS)
+ afb_api_require_class(api, PREINIT_REQUIRE_CLASS);
+#endif
+ return 0;
+}
+
+static int init(afb_api_t api)
+{
+ AFB_NOTICE("hello binding starting");
+#if defined(INIT_REQUIRE_API)
+ afb_api_require_api(api, INIT_REQUIRE_API, 1);