summaryrefslogtreecommitdiffstats
path: root/bindings/samples/hello3.c
diff options
context:
space:
mode:
authorJose Bollo <jose.bollo@iot.bzh>2018-07-12 10:59:48 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2018-07-24 16:28:32 +0200
commite17ae412245ba9afb33ff6a0f1f665b4d66d4da4 (patch)
tree698628c58b541007033ede6b4343dae921214da6 /bindings/samples/hello3.c
parent4c0f6ce66c66d39dc61ec661d88277c51d2fd9ae (diff)
coverage and test: Add tests
coverage values: - lines: 70.5 % - functions: 76.3 % Change-Id: Iaf802e84bbfa57502bbbac8c3b567b14c01608b6 Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'bindings/samples/hello3.c')
-rw-r--r--bindings/samples/hello3.c312
1 files changed, 302 insertions, 10 deletions
diff --git a/bindings/samples/hello3.c b/bindings/samples/hello3.c
index f49b3365..477e47bd 100644
--- a/bindings/samples/hello3.c
+++ b/bindings/samples/hello3.c
@@ -18,14 +18,24 @@
#include <stdio.h>
#include <string.h>
#include <pthread.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <json-c/json.h>
#define AFB_BINDING_VERSION 3
#include <afb/afb-binding.h>
+#if !defined(APINAME)
+#define APINAME "hello3"
+#endif
+
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+/**************************************************************************/
+
struct event
{
struct event *next;
@@ -116,6 +126,30 @@ static int event_broadcast(struct json_object *args, const char *tag)
return e ? afb_event_broadcast(e->event, json_object_get(args)) : -1;
}
+/**************************************************************************/
+
+struct api
+{
+ struct api *next;
+ afb_api_t api;
+ char name[1];
+};
+
+static struct api *apis = 0;
+
+/* search the api of name */
+static struct api *searchapi(const char *name, struct api ***previous)
+{
+ struct api *a, **p = &apis;
+ while((a = *p) && strcmp(a->name, name))
+ p = &a->next;
+ if (previous)
+ *previous = p;
+ return a;
+}
+
+/**************************************************************************/
+
// Sample Generic Ping Debug API
static void ping(afb_req_t request, json_object *jresp, const char *tag)
{
@@ -451,23 +485,107 @@ static void info (afb_req_t request)
afb_req_reply(request, afb_req_get_client_info(request), NULL, NULL);
}
-static int preinit(afb_api_t api)
+static void eventloop (afb_req_t request)
{
- AFB_NOTICE("hello binding comes to live");
- return 0;
+ afb_api_t api = afb_req_get_api(request);
+ struct sd_event *ev = afb_api_get_event_loop(api);
+ afb_req_reply(request, NULL, ev ? NULL : "no-event-loop", NULL);
}
-static int init(afb_api_t api)
+static void dbus (afb_req_t request)
{
- AFB_NOTICE("hello binding starting");
- return 0;
+ afb_api_t api = afb_req_get_api(request);
+ json_object *json = afb_req_json(request);
+ struct sd_bus *bus = (json_object_get_boolean(json) ? afb_api_get_system_bus : afb_api_get_user_bus)(api);
+ afb_req_reply(request, NULL, bus ? NULL : "no-bus", NULL);
}
-static void onevent(afb_api_t api, const char *event, struct json_object *object)
+static void replycount (afb_req_t request)
{
- AFB_NOTICE("received event %s(%s)", event, json_object_to_json_string(object));
+ json_object *json = afb_req_json(request);
+ int count = json_object_get_int(json);
+ while (count-- > 0)
+ afb_req_reply(request, NULL, NULL, NULL);
}
+static void get(afb_req_t request)
+{
+ struct afb_arg arg = afb_req_get(request, "name");
+ const char *name, *value, *path;
+
+ if (!arg.name || !arg.value)
+ afb_req_reply(request, NULL, "invalid", "the parameter 'name' is missing");
+ else {
+ name = arg.name;
+ value = afb_req_value(request, name);
+ path = afb_req_path(request, name);
+ afb_req_reply_f(request, NULL, NULL, "found for '%s': %s", name, value ?: path ?: "NULL");
+ }
+}
+
+static void ref(afb_req_t request)
+{
+ afb_req_addref(request);
+ afb_req_reply(request, NULL, NULL, NULL);
+ afb_req_unref(request);
+}
+
+static void rootdir (afb_req_t request)
+{
+ ssize_t s;
+ afb_api_t api = afb_req_get_api(request);
+ int fd = afb_api_rootdir_get_fd(api);
+ char buffer[150], root[1025];
+ sprintf(buffer, "/proc/self/fd/%d", fd);
+ s = readlink(buffer, root, sizeof root - 1);
+ if (s < 0)
+ afb_req_reply_f(request, NULL, "error", "can't readlink %s: %m", buffer);
+ else {
+ root[s] = 0;
+ afb_req_reply(request, json_object_new_string(root), NULL, NULL);
+ }
+}
+
+static void locale (afb_req_t request)
+{
+ char buffer[150], root[1025];
+ const char *lang, *file;
+ ssize_t s;
+ json_object *json = afb_req_json(request), *x;
+ afb_api_t api = afb_req_get_api(request);
+ int fd;
+
+ lang = NULL;
+ if (json_object_is_type(json, json_type_string))
+ file = json_object_get_string(json);
+ else {
+ if (!json_object_object_get_ex(json, "file", &x)) {
+ afb_req_reply(request, NULL, "invalid", "no file");
+ return;
+ }
+ file = json_object_get_string(x);
+ if (json_object_object_get_ex(json, "lang", &x))
+ lang = json_object_get_string(x);
+ }
+
+ fd = afb_api_rootdir_open_locale(api, file, O_RDONLY, lang);
+ if (fd < 0)
+ afb_req_reply_f(request, NULL, "error", "can't open %s [%s]: %m", file?:"NULL", lang?:"NULL");
+ else {
+ sprintf(buffer, "/proc/self/fd/%d", fd);
+ s = readlink(buffer, root, sizeof root - 1);
+ if (s < 0)
+ afb_req_reply_f(request, NULL, "error", "can't readlink %s: %m", buffer);
+ else {
+ root[s] = 0;
+ afb_req_reply(request, json_object_new_string(root), NULL, NULL);
+ }
+ close(fd);
+ }
+}
+
+static void api (afb_req_t request);
+
// 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_v3 verbs[]= {
@@ -499,12 +617,186 @@ static const struct afb_verb_v3 verbs[]= {
{ .verb="setctxif", .callback=setctx, .vcbdata = (void*)(intptr_t)0 },
{ .verb="getctx", .callback=getctx },
{ .verb="info", .callback=info },
+ { .verb="eventloop", .callback=eventloop },
+ { .verb="dbus", .callback=dbus },
+ { .verb="reply-count", .callback=replycount },
+ { .verb="get", .callback=get},
+ { .verb="ref", .callback=ref},
+ { .verb="rootdir", .callback=rootdir},
+ { .verb="locale", .callback=locale},
+ { .verb="api", .callback=api},
{ .verb=NULL}
};
-#if !defined(APINAME)
-#define APINAME "hello3"
+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);
#endif
+ afb_api_add_alias(api, api->apiname, "fakename");
+ return 0;
+}
+
+static void onevent(afb_api_t api, const char *event, struct json_object *object)
+{
+ AFB_NOTICE("received event %s(%s)", event, json_object_to_json_string(object));
+}
const struct afb_binding_v3 afbBindingV3 = {
.api = APINAME,