diff options
Diffstat (limited to 'plugins/samples')
-rw-r--r-- | plugins/samples/AuthLogin.c | 129 | ||||
-rw-r--r-- | plugins/samples/CMakeLists.txt | 63 | ||||
-rw-r--r-- | plugins/samples/DemoContext.c | 160 | ||||
-rw-r--r-- | plugins/samples/DemoPost.c | 100 | ||||
-rw-r--r-- | plugins/samples/HelloWorld.c | 279 | ||||
-rw-r--r-- | plugins/samples/export.map | 1 | ||||
-rw-r--r-- | plugins/samples/tic-tac-toe.c | 605 |
7 files changed, 0 insertions, 1337 deletions
diff --git a/plugins/samples/AuthLogin.c b/plugins/samples/AuthLogin.c deleted file mode 100644 index efecf240..00000000 --- a/plugins/samples/AuthLogin.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2015, 2016 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <json-c/json.h> - -#include <afb/afb-plugin.h> - -// Dummy sample of Client Application Context -typedef struct { - int something; - void *whateveryouwant; -} MyClientApplicationHandle; - - -// This function is call when Client Session Context is removed -// Note: when freeCtxCB==NULL standard free/malloc is called -static void clientContextFree(void *context) { - fprintf (stderr,"Plugin[token] Closing Session\n"); - free (context); -} - -// Request Creation of new context if it does not exist -static void clientContextConnect (struct afb_req request) -{ - json_object *jresp; - - // add an application specific client context to session - afb_req_context_set(request, malloc (sizeof (MyClientApplicationHandle)), clientContextFree); - - // do something intelligent to check if we should or not update level of assurance from 0(anonymous) to 1(logged) - afb_req_session_set_LOA(request, 1); - - // Send response to UI - jresp = json_object_new_object(); - json_object_object_add(jresp, "token", json_object_new_string ("A New Token and Session Context Was Created")); - - afb_req_success(request, jresp, NULL); - -} - -// Before entering here token will be check and renew -static void clientContextRefresh (struct afb_req request) { - json_object *jresp; - - - jresp = json_object_new_object(); - json_object_object_add(jresp, "token", json_object_new_string ("Token was refreshed")); - - afb_req_success(request, jresp, NULL); -} - - -// Session token will we verified before entering here -static void clientContextCheck (struct afb_req request) { - - json_object *jresp = json_object_new_object(); - json_object_object_add(jresp, "isvalid", json_object_new_boolean (TRUE)); - - afb_req_success(request, jresp, NULL); -} - - -// Close and Free context -static void clientContextLogout (struct afb_req request) { - json_object *jresp; - - /* after this call token will be reset - * - no further access to API will be possible - * - every context from any used plugin will be freed - */ - - jresp = json_object_new_object(); - json_object_object_add(jresp, "info", json_object_new_string ("Token and all resources are released")); - - // WARNING: if you free context resource manually here do not forget to set *request.context=NULL; - afb_req_success(request, jresp, NULL); - - afb_req_session_set_LOA(request, 0); -} -// Close and Free context -static void clientGetPing (struct afb_req request) { - static int count=0; - json_object *jresp; - - jresp = json_object_new_object(); - json_object_object_add(jresp, "count", json_object_new_int (count ++)); - - afb_req_success(request, jresp, NULL); -} - - -static const struct AFB_verb_desc_v1 verbs[]= { - {"ping" , AFB_SESSION_NONE , clientGetPing ,"Ping Rest Test Service"}, - {"connect" , AFB_SESSION_LOA_EQ_0 | AFB_SESSION_RENEW, clientContextConnect,"Connect/Login Client"}, - {"refresh" , AFB_SESSION_LOA_GE_1 | AFB_SESSION_RENEW, clientContextRefresh,"Refresh Client Authentication Token"}, - {"check" , AFB_SESSION_LOA_GE_1 , clientContextCheck ,"Check Client Authentication Token"}, - {"logout" , AFB_SESSION_LOA_GE_1 | AFB_SESSION_CLOSE, clientContextLogout ,"Logout Client and Free resources"}, - {NULL} -}; - -static const struct AFB_plugin plugin_desc = { - .type = AFB_PLUGIN_VERSION_1, - .v1 = { - .info = "Application Framework Binder Authentication sample", - .prefix = "auth", - .verbs = verbs - } -}; - -const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf) -{ - return &plugin_desc; -} diff --git a/plugins/samples/CMakeLists.txt b/plugins/samples/CMakeLists.txt deleted file mode 100644 index eb6e0112..00000000 --- a/plugins/samples/CMakeLists.txt +++ /dev/null @@ -1,63 +0,0 @@ - -INCLUDE_DIRECTORIES(${include_dirs}) - -################################################## -# AuthLogin -################################################## -ADD_LIBRARY(authLogin MODULE AuthLogin.c) -SET_TARGET_PROPERTIES(authLogin PROPERTIES - PREFIX "" - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" -) -TARGET_LINK_LIBRARIES(authLogin ${link_libraries}) -INSTALL(TARGETS authLogin - LIBRARY DESTINATION ${plugin_install_dir}) - -################################################## -# DemoContext -################################################## -ADD_LIBRARY(demoContext MODULE DemoContext.c) -SET_TARGET_PROPERTIES(demoContext PROPERTIES - PREFIX "" - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" -) -TARGET_LINK_LIBRARIES(demoContext ${link_libraries}) -INSTALL(TARGETS demoContext - LIBRARY DESTINATION ${plugin_install_dir}) - -################################################## -# DemoPost -################################################## -ADD_LIBRARY(demoPost MODULE DemoPost.c) -SET_TARGET_PROPERTIES(demoPost PROPERTIES - PREFIX "" - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" -) -TARGET_LINK_LIBRARIES(demoPost ${link_libraries}) -INSTALL(TARGETS demoPost - LIBRARY DESTINATION ${plugin_install_dir}) - -################################################## -# HelloWorld -################################################## -ADD_LIBRARY(helloWorld MODULE HelloWorld.c) -SET_TARGET_PROPERTIES(helloWorld PROPERTIES - PREFIX "" - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" -) -TARGET_LINK_LIBRARIES(helloWorld ${link_libraries}) -INSTALL(TARGETS helloWorld - LIBRARY DESTINATION ${plugin_install_dir}) - -################################################## -# tic-tac-toe -################################################## -ADD_LIBRARY(tic-tac-toe MODULE tic-tac-toe.c) -SET_TARGET_PROPERTIES(tic-tac-toe PROPERTIES - PREFIX "" - LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" -) -TARGET_LINK_LIBRARIES(tic-tac-toe ${link_libraries}) -INSTALL(TARGETS tic-tac-toe - LIBRARY DESTINATION ${plugin_install_dir}) - diff --git a/plugins/samples/DemoContext.c b/plugins/samples/DemoContext.c deleted file mode 100644 index ef703759..00000000 --- a/plugins/samples/DemoContext.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2015, 2016 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <json-c/json.h> - -#include <afb/afb-plugin.h> - -typedef struct { - /* - * client context is attached a session but private to a each plugin. - * Context is passed to each API under request->context - * - * Note: - * -client context is free when a session is closed. Developer should not - * forget that even if context is private to each plugin, session is unique - * to a client. When session close, every plugin are notified to free there - * private context. - * -by default standard "free" function from libc is used to free context. - * Developer may define it own under plugin->freeCB. This call received - * FreeCtxCb(void *ClientCtx, void*PluginHandle, char*SessionUUID) if - * FreeCtxCb=(void*)-1 then context wont be free by session manager. - * -when an API use AFB_SESSION_RESET this close the session and each plugin - * will be notified to free ressources. - */ - - int count; - char *abcd; - -} MyClientContextT; - -// This function is call at session open time. Any client trying to -// call it with an already open session will be denied. -// Ex: http://localhost:1234/api/context/create?token=123456789 -static void myCreate (struct afb_req request) -{ - MyClientContextT *ctx = malloc (sizeof (MyClientContextT)); - - // store something in our plugin private client context - ctx->count = 0; - ctx->abcd = "SomeThingUseful"; - - afb_req_context_set(request, ctx, free); - afb_req_success_f(request, NULL, "SUCCESS: create client context for plugin [%s]", ctx->abcd); -} - -// This function can only be called with a valid token. Token should be renew before -// session timeout a standard renew api is avaliable at /api/token/renew this API -// can be called automatically with <token-renew> HTML5 widget. -// ex: http://localhost:1234/api/context/action?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx -static void myAction (struct afb_req request) -{ - MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request); - - // store something in our plugin private client context - ctx->count++; - afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", ctx->abcd, ctx->count); -} - -// After execution of this function, client session will be close and if they -// created a context [request->context != NULL] every plugins will be notified -// that they should free context resources. -// ex: http://localhost:1234/api/context/close?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx -static void myClose (struct afb_req request) -{ - MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request); - - // store something in our plugin private client context - ctx->count++; - afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", ctx->abcd, ctx->count); -} - -// Set the LOA -static void setLOA(struct afb_req request, unsigned loa) -{ - if (afb_req_session_set_LOA(request, loa)) - afb_req_success_f(request, NULL, "loa set to %u", loa); - else - afb_req_fail_f(request, "failed", "can't set loa to %u", loa); -} - -static void clientSetLOA0(struct afb_req request) -{ - setLOA(request, 0); -} - -static void clientSetLOA1(struct afb_req request) -{ - setLOA(request, 1); -} - -static void clientSetLOA2(struct afb_req request) -{ - setLOA(request, 2); -} - -static void clientSetLOA3(struct afb_req request) -{ - setLOA(request, 3); -} - -static void clientCheckLOA(struct afb_req request) -{ - afb_req_success(request, NULL, "LOA checked and okay"); -} - -// NOTE: this sample does not use session to keep test a basic as possible -// in real application most APIs should be protected with AFB_SESSION_CHECK -static const struct AFB_verb_desc_v1 verbs[]= { - {"create", AFB_SESSION_CREATE, myCreate , "Create a new session"}, - {"action", AFB_SESSION_CHECK , myAction , "Use Session Context"}, - {"close" , AFB_SESSION_CLOSE , myClose , "Free Context"}, - {"set_loa_0", AFB_SESSION_RENEW, clientSetLOA0 ,"Set level of assurance to 0"}, - {"set_loa_1", AFB_SESSION_RENEW, clientSetLOA1 ,"Set level of assurance to 1"}, - {"set_loa_2", AFB_SESSION_RENEW, clientSetLOA2 ,"Set level of assurance to 2"}, - {"set_loa_3", AFB_SESSION_RENEW, clientSetLOA3 ,"Set level of assurance to 3"}, - {"check_loa_ge_0", AFB_SESSION_LOA_GE_0, clientCheckLOA ,"Check whether level of assurance is greater or equal to 0"}, - {"check_loa_ge_1", AFB_SESSION_LOA_GE_1, clientCheckLOA ,"Check whether level of assurance is greater or equal to 1"}, - {"check_loa_ge_2", AFB_SESSION_LOA_GE_2, clientCheckLOA ,"Check whether level of assurance is greater or equal to 2"}, - {"check_loa_ge_3", AFB_SESSION_LOA_GE_3, clientCheckLOA ,"Check whether level of assurance is greater or equal to 3"}, - {"check_loa_le_0", AFB_SESSION_LOA_LE_0, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 0"}, - {"check_loa_le_1", AFB_SESSION_LOA_LE_1, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 1"}, - {"check_loa_le_2", AFB_SESSION_LOA_LE_2, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 2"}, - {"check_loa_le_3", AFB_SESSION_LOA_LE_3, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 3"}, - {"check_loa_eq_0", AFB_SESSION_LOA_EQ_0, clientCheckLOA ,"Check whether level of assurance is equal to 0"}, - {"check_loa_eq_1", AFB_SESSION_LOA_EQ_1, clientCheckLOA ,"Check whether level of assurance is equal to 1"}, - {"check_loa_eq_2", AFB_SESSION_LOA_EQ_2, clientCheckLOA ,"Check whether level of assurance is equal to 2"}, - {"check_loa_eq_3", AFB_SESSION_LOA_EQ_3, clientCheckLOA ,"Check whether level of assurance is equal to 3"}, - {NULL} -}; - -static const struct AFB_plugin plugin_desc = { - .type = AFB_PLUGIN_VERSION_1, - .v1 = { - .info = "Sample of Client Context Usage", - .prefix = "context", - .verbs = verbs, - } -}; - -const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf) -{ - return &plugin_desc; -} - diff --git a/plugins/samples/DemoPost.c b/plugins/samples/DemoPost.c deleted file mode 100644 index b61b91c4..00000000 --- a/plugins/samples/DemoPost.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2015, 2016 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> -#include <json-c/json.h> - -#include <afb/afb-plugin.h> - - -// Sample Generic Ping Debug API -static void getPingTest(struct afb_req request) -{ - static int pingcount = 0; - json_object *query = afb_req_json(request); - - afb_req_success_f(request, query, "Ping Binder Daemon count=%d", ++pingcount); -} - -// With content-type=json data are directly avaliable in request->post->data -static void GetJsonByPost (struct afb_req request) -{ - struct afb_arg arg; - json_object* jresp; - json_object *query = afb_req_json(request); - - arg = afb_req_get(request, ""); - jresp = arg.value ? json_tokener_parse(arg.value) : NULL; - afb_req_success_f(request, jresp, "GetJsonByPost query={%s}", json_object_to_json_string(query)); -} - -// Upload a file and execute a function when upload is done -static void Uploads (struct afb_req request, const char *destination) -{ - struct afb_arg a = afb_req_get(request, "file"); - if (a.value == NULL || *a.value == 0) - afb_req_fail(request, "failed", "no file selected"); - else - afb_req_success_f(request, NULL, "uploaded file %s of path %s for destination %s", a.value, a.path, destination); -} - -// Upload a file and execute a function when upload is done -static void UploadAppli (struct afb_req request) -{ - Uploads(request, "applications"); -} - -// Simples Upload case just upload a file -static void UploadMusic (struct afb_req request) -{ - Uploads(request, "musics"); -} - -// PostForm callback is called multiple times (one or each key within form, or once per file buffer) -// When file has been fully uploaded call is call with item==NULL -static void UploadImage (struct afb_req request) -{ - Uploads(request, "images"); -} - - -// NOTE: this sample does not use session to keep test a basic as possible -// in real application upload-xxx should be protected with AFB_SESSION_CHECK -static const struct AFB_verb_desc_v1 verbs[]= { - {"ping" , AFB_SESSION_NONE , getPingTest ,"Ping Rest Test Service"}, - {"upload-json" , AFB_SESSION_NONE , GetJsonByPost ,"Demo for Json Buffer on Post"}, - {"upload-image" , AFB_SESSION_NONE , UploadImage ,"Demo for file upload"}, - {"upload-music" , AFB_SESSION_NONE , UploadMusic ,"Demo for file upload"}, - {"upload-appli" , AFB_SESSION_NONE , UploadAppli ,"Demo for file upload"}, - {NULL} -}; - -static const struct AFB_plugin plugin_desc = { - .type = AFB_PLUGIN_VERSION_1, - .v1 = { - .info = "Sample with Post Upload Files", - .prefix = "post", - .verbs = verbs - } -}; - -const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf) -{ - return &plugin_desc; -}; diff --git a/plugins/samples/HelloWorld.c b/plugins/samples/HelloWorld.c deleted file mode 100644 index b6f49b78..00000000 --- a/plugins/samples/HelloWorld.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2015, 2016 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> -#include <json-c/json.h> - -#include <afb/afb-plugin.h> - -const struct AFB_interface *interface; - -struct event -{ - struct event *next; - struct afb_event event; - char tag[1]; -}; - -static struct event *events = 0; - -/* searchs the event of tag */ -static struct event *event_get(const char *tag) -{ - struct event *e = events; - while(e && strcmp(e->tag, tag)) - e = e->next; - return e; -} - -/* deletes the event of tag */ -static int event_del(const char *tag) -{ - struct event *e, **p; - - /* check exists */ - e = event_get(tag); - if (!e) return -1; - - /* unlink */ - p = &events; - while(*p != e) p = &(*p)->next; - *p = e->next; - - /* destroys */ - afb_event_drop(e->event); - free(e); - return 0; -} - -/* creates the event of tag */ -static int event_add(const char *tag, const char *name) -{ - struct event *e; - - /* check valid tag */ - e = event_get(tag); - if (e) return -1; - - /* creation */ - e = malloc(strlen(tag) + sizeof *e); - if (!e) return -1; - strcpy(e->tag, tag); - - /* make the event */ - e->event = afb_daemon_make_event(interface->daemon, name); - if (!e->event.closure) { free(e); return -1; } - - /* link */ - e->next = events; - events = e; - return 0; -} - -static int event_subscribe(struct afb_req request, const char *tag) -{ - struct event *e; - e = event_get(tag); - return e ? afb_req_subscribe(request, e->event) : -1; -} - -static int event_unsubscribe(struct afb_req request, const char *tag) -{ - struct event *e; - e = event_get(tag); - return e ? afb_req_unsubscribe(request, e->event) : -1; -} - -static int event_push(struct json_object *args, const char *tag) -{ - struct event *e; - e = event_get(tag); - return e ? afb_event_push(e->event, json_object_get(args)) : -1; -} - -// Sample Generic Ping Debug API -static void ping(struct afb_req request, json_object *jresp, const char *tag) -{ - static int pingcount = 0; - json_object *query = afb_req_json(request); - afb_req_success_f(request, jresp, "Ping Binder Daemon tag=%s count=%d query=%s", tag, ++pingcount, json_object_to_json_string(query)); -} - -static void pingSample (struct afb_req request) -{ - ping(request, json_object_new_string ("Some String"), "pingSample"); -} - -static void pingFail (struct afb_req request) -{ - afb_req_fail(request, "failed", "Ping Binder Daemon fails"); -} - -static void pingNull (struct afb_req request) -{ - ping(request, NULL, "pingNull"); -} - -static void pingBug (struct afb_req request) -{ - ping((struct afb_req){NULL,NULL,NULL}, NULL, "pingBug"); -} - -static void pingEvent(struct afb_req request) -{ - json_object *query = afb_req_json(request); - afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query)); - ping(request, json_object_get(query), "event"); -} - - -// For samples https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/ -static void pingJson (struct afb_req request) { - json_object *jresp, *embed; - - jresp = json_object_new_object(); - json_object_object_add(jresp, "myString", json_object_new_string ("Some String")); - json_object_object_add(jresp, "myInt", json_object_new_int (1234)); - - embed = json_object_new_object(); - json_object_object_add(embed, "subObjString", json_object_new_string ("Some String")); - json_object_object_add(embed, "subObjInt", json_object_new_int (5678)); - - json_object_object_add(jresp,"eobj", embed); - - ping(request, jresp, "pingJson"); -} - -static void subcallcb (void *prequest, int iserror, json_object *object) -{ - struct afb_req request = afb_req_unstore(prequest); - if (iserror) - afb_req_fail(request, "failed", json_object_to_json_string(object)); - else - afb_req_success(request, object, NULL); - afb_req_unref(request); -} - -static void subcall (struct afb_req request) -{ - const char *api = afb_req_value(request, "api"); - const char *verb = afb_req_value(request, "verb"); - const char *args = afb_req_value(request, "args"); - json_object *object = api && verb && args ? json_tokener_parse(args) : NULL; - - if (object == NULL) - afb_req_fail(request, "failed", "bad arguments"); - else - afb_req_subcall(request, api, verb, object, subcallcb, afb_req_store(request)); -} - -static void eventadd (struct afb_req request) -{ - const char *tag = afb_req_value(request, "tag"); - const char *name = afb_req_value(request, "name"); - - if (tag == NULL || name == NULL) - afb_req_fail(request, "failed", "bad arguments"); - else if (0 != event_add(tag, name)) - afb_req_fail(request, "failed", "creation error"); - else - afb_req_success(request, NULL, NULL); -} - -static void eventdel (struct afb_req request) -{ - const char *tag = afb_req_value(request, "tag"); - - if (tag == NULL) - afb_req_fail(request, "failed", "bad arguments"); - else if (0 != event_del(tag)) - afb_req_fail(request, "failed", "deletion error"); - else - afb_req_success(request, NULL, NULL); -} - -static void eventsub (struct afb_req request) -{ - const char *tag = afb_req_value(request, "tag"); - - if (tag == NULL) - afb_req_fail(request, "failed", "bad arguments"); - else if (0 != event_subscribe(request, tag)) - afb_req_fail(request, "failed", "subscription error"); - else - afb_req_success(request, NULL, NULL); -} - -static void eventunsub (struct afb_req request) -{ - const char *tag = afb_req_value(request, "tag"); - - if (tag == NULL) - afb_req_fail(request, "failed", "bad arguments"); - else if (0 != event_unsubscribe(request, tag)) - afb_req_fail(request, "failed", "unsubscription error"); - else - afb_req_success(request, NULL, NULL); -} - -static void eventpush (struct afb_req request) -{ - const char *tag = afb_req_value(request, "tag"); - const char *data = afb_req_value(request, "data"); - json_object *object = data ? json_tokener_parse(data) : NULL; - - if (tag == NULL) - afb_req_fail(request, "failed", "bad arguments"); - else if (0 > event_push(object, tag)) - afb_req_fail(request, "failed", "push error"); - else - afb_req_success(request, NULL, NULL); -} - -// NOTE: this sample does not use session to keep test a basic as possible -// in real application most APIs should be protected with AFB_SESSION_CHECK -static const struct AFB_verb_desc_v1 verbs[]= { - {"ping" , AFB_SESSION_NONE, pingSample , "Ping Application Framework"}, - {"pingfail" , AFB_SESSION_NONE, pingFail , "Fails"}, - {"pingnull" , AFB_SESSION_NONE, pingNull , "Return NULL"}, - {"pingbug" , AFB_SESSION_NONE, pingBug , "Do a Memory Violation"}, - {"pingJson" , AFB_SESSION_NONE, pingJson , "Return a JSON object"}, - {"pingevent", AFB_SESSION_NONE, pingEvent , "Send an event"}, - {"subcall", AFB_SESSION_NONE, subcall , "Call api/verb(args)"}, - {"eventadd", AFB_SESSION_NONE, eventadd , "adds the event of 'name' for the 'tag'"}, - {"eventdel", AFB_SESSION_NONE, eventdel , "deletes the event of 'tag'"}, - {"eventsub", AFB_SESSION_NONE, eventsub , "subscribes to the event of 'tag'"}, - {"eventunsub",AFB_SESSION_NONE, eventunsub , "unsubscribes to the event of 'tag'"}, - {"eventpush", AFB_SESSION_NONE, eventpush , "pushs the event of 'tag' with the 'data'"}, - {NULL} -}; - -static const struct AFB_plugin plugin_desc = { - .type = AFB_PLUGIN_VERSION_1, - .v1 = { - .info = "Minimal Hello World Sample", - .prefix = "hello", - .verbs = verbs - } -}; - -const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf) -{ - interface = itf; - return &plugin_desc; -} diff --git a/plugins/samples/export.map b/plugins/samples/export.map deleted file mode 100644 index e2da85ca..00000000 --- a/plugins/samples/export.map +++ /dev/null @@ -1 +0,0 @@ -{ global: pluginAfbV1Register; local: *; }; diff --git a/plugins/samples/tic-tac-toe.c b/plugins/samples/tic-tac-toe.c deleted file mode 100644 index 31682d94..00000000 --- a/plugins/samples/tic-tac-toe.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (C) 2016 "IoT.bzh" - * Author José Bollo <jose.bollo@iot.bzh> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <string.h> -#include <json-c/json.h> - -#include <afb/afb-plugin.h> - -/* - * the interface to afb-daemon - */ -const struct AFB_interface *afbitf; - -/* - * definition of waiters - */ -struct waiter -{ - struct waiter *next; - struct afb_req req; -}; - -/* - * definition of a board - */ -struct board -{ - struct board *next; - int use_count; - int moves; - int history[9]; - int id; - int level; - char board[9]; - struct waiter *waiters; -}; - -/* - * list of boards - */ -static struct board *all_boards; - -/* - * Searchs a board having the 'id'. - * Returns it if found or NULL otherwise. - */ -static struct board *search_board(int id) -{ - struct board *board = all_boards; - while (board != NULL && board->id != id) - board = board->next; - return board; -} - -/* - * Creates a new board and returns it. - */ -static struct board *get_new_board() -{ - /* allocation */ - struct board *board = calloc(1, sizeof *board); - - /* initialisation */ - memset(board->board, ' ', sizeof board->board); - board->use_count = 1; - board->level = 1; - board->moves = 0; - do { - board->id = (rand() >> 2) % 1000; - } while(board->id == 0 || search_board(board->id) != NULL); - - /* link */ - board->next = all_boards; - all_boards = board; - return board; -} - -/* - * Release a board - */ -static void release_board(struct board *board) -{ - /* decrease the reference count ... */ - if (--board->use_count == 0) { - /* ... no more use */ - /* unlink from the list of boards */ - struct board **prv = &all_boards; - while (*prv != NULL && *prv != board) - prv = &(*prv)->next; - if (*prv != NULL) - *prv = board->next; - /* release the used memory */ - free(board); - } -} - -/* - * Checks who wins - * Returns zero if there is no winner - * Returns the char of the winner if a player won - */ -static char winner(const char b[9]) -{ - int i; - char c; - - /* check diagonals */ - c = b[4]; - if (c != ' ') { - if (b[0] == c && b[8] == c) - return c; - if (b[2] == c && b[6] == c) - return c; - } - - /* check lines */ - for (i = 0 ; i <= 6 ; i += 3) { - c = b[i]; - if (c != ' ' && b[i+1] == c && b[i+2] == c) - return c; - } - - /* check columns */ - for (i = 0 ; i <= 2 ; i++) { - c = b[i]; - if (c != ' ' && b[i+3] == c && b[i+6] == c) - return c; - } - - return 0; -} - -/* get the color (X or 0) of the move of index 'move' */ -static char color(int move) -{ - return (move & 1) == 0 ? 'X' : '0'; -} - -/* adds the move to the board */ -static void add_move(struct board *board, int index) -{ - int imove = board->moves++; - board->history[imove] = index; - board->board[index] = color(imove); -} - -/* get a random possible move index from the board described by 'b' */ -static int get_random_move(char b[9]) -{ - int index = rand() % 9; - while (b[index] != ' ') - index = (index + 1) % 9; - return index; -} - -/* - * Scores the position described by 'b' - * for the player of color 'c' using an analysis of 'depth'. - * Returns 1 if player 'c' will win. - * Returns -1 if opponent of player 'c' will win. - * returns 0 otherwise. - */ -static int score_position(char b[9], char c, int depth) -{ - int i, t, r; - - /* check if winner */ - if (winner(b) == c) - return 1; - - /* when depth of analysis is reached return unknown case */ - if (--depth == 0) - return 0; - - /* switch to the opponent */ - c = (char)('O' + 'X' - c); - - /* inspect opponent moves */ - r = 1; - for (i = 0 ; i < 9 ; i++) { - if (b[i] == ' ') { - b[i] = c; - t = score_position(b, c, depth); - b[i] = ' '; - if (t > 0) - return -1; /* opponent will win */ - - if (t == 0) - r = 0; /* something not clear */ - } - } - return r; -} - -/* get one move: return the computed index of the move */ -static int get_move(struct board *board) -{ - int index, depth, t, f; - char c; - char b[9]; - - /* compute the depth */ - depth = board->level - 1; - if (board->moves + depth > 9) - depth = 9 - board->moves; - - /* case of null depth */ - if (depth == 0) - return get_random_move(board->board); - - /* depth and more */ - memcpy(b, board->board, 9); - c = color(board->moves); - f = 0; - for (index = 0 ; index < 9 ; index++) { - if (board->board[index] == ' ') { - board->board[index] = c; - t = score_position(board->board, c, depth); - board->board[index] = ' '; - if (t > 0) - return index; - if (t < 0) - b[index] = '+'; - else - f = 1; - } - } - return get_random_move(f ? b : board->board); -} - -/* - * get the board description - */ -static struct json_object *describe(struct board *board) -{ - int i; - char w; - struct json_object *resu, *arr; - - resu = json_object_new_object(); - - json_object_object_add(resu, "boardid", json_object_new_int(board->id)); - json_object_object_add(resu, "level", json_object_new_int(board->level)); - - arr = json_object_new_array(); - json_object_object_add(resu, "board", arr); - for (i = 0 ; i < 9 ; i++) - json_object_array_add(arr, - json_object_new_string_len(&board->board[i], 1)); - - arr = json_object_new_array(); - json_object_object_add(resu, "history", arr); - for (i = 0 ; i < board->moves ; i++) - json_object_array_add(arr, json_object_new_int(board->history[i])); - - w = winner(board->board); - if (w) - json_object_object_add(resu, "winner", json_object_new_string_len(&w, 1)); - else if (board->moves == 9) - json_object_object_add(resu, "winner", json_object_new_string("none")); - - return resu; -} - -/* - * signals a change of the board - */ -static void changed(struct board *board, const char *reason) -{ - struct waiter *waiter, *next; - struct json_object *description; - - /* get the description */ - description = describe(board); - - waiter = board->waiters; - board->waiters = NULL; - while (waiter != NULL) { - next = waiter->next; - afb_req_success(waiter->req, json_object_get(description), reason); - afb_req_unref(waiter->req); - free(waiter); - waiter = next; - } - - afb_daemon_broadcast_event(afbitf->daemon, reason, description); -} - -/* - * retrieves the board of the request - */ -static inline struct board *board_of_req(struct afb_req req) -{ - return afb_req_context(req, (void*)get_new_board, (void*)release_board); -} - -/* - * start a new game - */ -static void new(struct afb_req req) -{ - struct board *board; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'new' called for boardid %d", board->id); - - /* reset the game */ - memset(board->board, ' ', sizeof board->board); - board->moves = 0; - - /* replies */ - afb_req_success(req, NULL, NULL); - - /* signal change */ - changed(board, "new"); -} - -/* - * get the board - */ -static void board(struct afb_req req) -{ - struct board *board; - struct json_object *description; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'board' called for boardid %d", board->id); - - /* describe the board */ - description = describe(board); - - /* send the board's description */ - afb_req_success(req, description, NULL); -} - -/* - * move a piece - */ -static void move(struct afb_req req) -{ - struct board *board; - int i; - const char *index; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'move' called for boardid %d", board->id); - - /* retrieves the arguments of the move */ - index = afb_req_value(req, "index"); - i = index == NULL ? -1 : atoi(index); - - /* checks validity of arguments */ - if (i < 0 || i > 8) { - WARNING(afbitf, "can't move to %s: %s", index?:"?", index?"wrong value":"not set"); - afb_req_fail(req, "error", "bad request"); - return; - } - - /* checks validity of the state */ - if (winner(board->board) != 0) { - WARNING(afbitf, "can't move to %s: game is terminated", index); - afb_req_fail(req, "error", "game terminated"); - return; - } - - /* checks validity of the move */ - if (board->board[i] != ' ') { - WARNING(afbitf, "can't move to %s: room occupied", index); - afb_req_fail(req, "error", "occupied"); - return; - } - - /* applies the move */ - INFO(afbitf, "method 'move' for boardid %d, index=%s", board->id, index); - add_move(board, i); - - /* replies */ - afb_req_success(req, NULL, NULL); - - /* signals change */ - changed(board, "move"); -} - -/* - * set the level - */ -static void level(struct afb_req req) -{ - struct board *board; - int l; - const char *level; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'level' called for boardid %d", board->id); - - /* retrieves the arguments */ - level = afb_req_value(req, "level"); - l = level == NULL ? -1 : atoi(level); - - /* check validity of arguments */ - if (l < 1 || l > 10) { - WARNING(afbitf, "can't set level to %s: %s", level?:"?", level?"wrong value":"not set"); - afb_req_fail(req, "error", "bad request"); - return; - } - - /* set the level */ - INFO(afbitf, "method 'level' for boardid %d, level=%d", board->id, l); - board->level = l; - - /* replies */ - afb_req_success(req, NULL, NULL); - - /* signals change */ - changed(board, "level"); -} - -/* - * Join a board - */ -static void join(struct afb_req req) -{ - struct board *board, *new_board; - const char *id; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'join' called for boardid %d", board->id); - - /* retrieves the arguments */ - id = afb_req_value(req, "boardid"); - if (id == NULL) - goto bad_request; - - /* none is a special id for joining a new session */ - if (strcmp(id, "none") == 0) { - new_board = get_new_board(); - goto success; - } - - /* searchs the board to join */ - new_board = search_board(atoi(id)); - if (new_board == NULL) - goto bad_request; - - /* - * joining its board is stupid but possible - * however when called with the same stored pointer - * afb_req_context_set will not call the release - * function 'release_board'. So the use_count MUST not - * be incremented. - */ - if (new_board != board) - new_board->use_count++; - -success: - /* set the new board (and leaves the previous one) */ - afb_req_context_set(req, new_board, (void*)release_board); - - /* replies */ - afb_req_success(req, NULL, NULL); - return; - -bad_request: - WARNING(afbitf, "can't join boardid %s: %s", id ? : "?", !id ? "no boardid" : atoi(id) ? "not found" : "bad boardid"); - afb_req_fail(req, "error", "bad request"); - return; -} - -/* - * Undo the last move - */ -static void undo(struct afb_req req) -{ - struct board *board; - int i; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'undo' called for boardid %d", board->id); - - /* checks the state */ - if (board->moves == 0) { - WARNING(afbitf, "can't undo"); - afb_req_fail(req, "error", "bad request"); - return; - } - - /* undo the last move */ - i = board->history[--board->moves]; - board->board[i] = ' '; - - /* replies */ - afb_req_success(req, NULL, NULL); - - /* signals change */ - changed(board, "undo"); -} - -/* - * computer plays - */ -static void play(struct afb_req req) -{ - struct board *board; - int index; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'play' called for boardid %d", board->id); - - /* checks validity of the state */ - if (winner(board->board) != 0 || board->moves == 9) { - WARNING(afbitf, "can't play: game terminated (%s)", winner(board->board) ? "has winner" : "no room left"); - afb_req_fail(req, "error", "game terminated"); - return; - } - - /* gets the move and plays it */ - index = get_move(board); - add_move(board, index); - - /* replies */ - afb_req_success(req, describe(board), NULL); - - /* signals change */ - changed(board, "play"); -} - -static void wait(struct afb_req req) -{ - struct board *board; - struct waiter *waiter; - - /* retrieves the context for the session */ - board = board_of_req(req); - INFO(afbitf, "method 'wait' called for boardid %d", board->id); - - /* creates the waiter and enqueues it */ - waiter = calloc(1, sizeof *waiter); - waiter->req = req; - waiter->next = board->waiters; - afb_req_addref(req); - board->waiters = waiter; -} - -/* - * array of the verbs exported to afb-daemon - */ -static const struct AFB_verb_desc_v1 plugin_verbs[] = { - /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */ - { .name= "new", .session= AFB_SESSION_NONE, .callback= new, .info= "Starts a new game" }, - { .name= "play", .session= AFB_SESSION_NONE, .callback= play, .info= "Asks the server to play" }, - { .name= "move", .session= AFB_SESSION_NONE, .callback= move, .info= "Tells the client move" }, - { .name= "board", .session= AFB_SESSION_NONE, .callback= board, .info= "Get the current board" }, - { .name= "level", .session= AFB_SESSION_NONE, .callback= level, .info= "Set the server level" }, - { .name= "join", .session= AFB_SESSION_CHECK,.callback= join, .info= "Join a board" }, - { .name= "undo", .session= AFB_SESSION_NONE, .callback= undo, .info= "Undo the last move" }, - { .name= "wait", .session= AFB_SESSION_NONE, .callback= wait, .info= "Wait for a change" }, - { .name= NULL } /* marker for end of the array */ -}; - -/* - * description of the plugin for afb-daemon - */ -static const struct AFB_plugin plugin_description = -{ - /* description conforms to VERSION 1 */ - .type= AFB_PLUGIN_VERSION_1, - .v1= { /* fills the v1 field of the union when AFB_PLUGIN_VERSION_1 */ - .prefix= "tictactoe", /* the API name (or plugin name or prefix) */ - .info= "Sample tac-tac-toe game", /* short description of of the plugin */ - .verbs = plugin_verbs /* the array describing the verbs of the API */ - } -}; - -/* - * activation function for registering the plugin called by afb-daemon - */ -const struct AFB_plugin *pluginAfbV1Register(const struct AFB_interface *itf) -{ - afbitf = itf; // records the interface for accessing afb-daemon - return &plugin_description; // returns the description of the plugin -} - |