From 1500ad07f703b9cf51b38e16be35b2d5250a4015 Mon Sep 17 00:00:00 2001 From: Anjan Chanda <anjan.chanda@iopsys.eu> Date: Thu, 9 Jun 2022 10:55:57 +0200 Subject: [PATCH] libmapbus.so: from generic bus.h, implement for ubus --- src/Makefile | 9 +- src/bus.h | 53 ++++++++ src/cntlr.c | 3 +- src/cntlr_map.c | 1 + src/cntlr_ubus.c | 292 +----------------------------------------- src/cntlr_ubus.h | 24 ---- src/ubus.c | 320 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 385 insertions(+), 317 deletions(-) create mode 100644 src/bus.h create mode 100644 src/ubus.c diff --git a/src/Makefile b/src/Makefile index b045b998..a3a995bd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,6 +2,8 @@ EXECS = mapcontroller CFLAGS+=-I. -Iutils -D_GNU_SOURCE CFLAGS+= -g -Wall -Werror +LIBOBJS = ubus.o + OBJS = \ utils/debug.o \ utils/liblist.o \ @@ -34,14 +36,17 @@ HOOKS = pre-commit .PHONY: all check clean plugins FORCE -all: $(EXECS) plugins +all: libmapbus.so $(EXECS) plugins %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< mapcontroller: $(OBJS) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -L. -lmapbus + +libmapbus.so: $(LIBOBJS) + $(CC) -shared -Wl,-soname,libmapbus.so $^ -o $@ -lblobmsg_json -lubus plugins: @echo "$(plugin_subdirs)" diff --git a/src/bus.h b/src/bus.h new file mode 100644 index 00000000..aeedc3ae --- /dev/null +++ b/src/bus.h @@ -0,0 +1,53 @@ +/* + * bus.h - ipc abstraction header + * + * Copyright (C) 2019-2022 IOPSYS Software Solutions AB. All rights reserved. + * + * Author: anjan.chanda@iopsys.eu + * + */ + +#ifndef BUS_H +#define BUS_H + +extern int bus_init(void *userdata, void *cfgopts, void **bus); +extern void bus_exit(void *userdata, void *bus); + +typedef int (*op_t)(void *data, size_t len); + +struct bus_object_op { + const char *name; + op_t op; +}; + +struct bus_object { + const char *name; + size_t num_ops; + struct bus_object_op *ops; +}; + +extern int bus_add_object(void *bus, struct bus_object o); +extern void bus_del_object(void *bus, const char *objname); + +extern int bus_wait_for_object_timeout(void *bus, void *object, uint32_t tmo_msecs, void *res); + +extern int bus_call_object(void *bus, void *object, void *function, + void *request, size_t len, + void (*cb)(void *userdata, char *response, size_t len), + void *userdata, uint32_t timeout); + +extern int bus_register_object_notifier(void *bus, void *object, + void (*cb)(void *userdata, void *event, void *extra), + void *userdata, void **notifier); + +extern void bus_unregister_notifier(void *bus, void *notifier); + +extern int bus_register_event_notifier(void *bus, void *event, + void (*cb)(void *userdata, void *event, void *extra), + void *userdata, void **notifier); + +extern void bus_notify_event(void *bus, void *event, void *extra); + +extern char *bus_strerror(int num, char *string, size_t len); + +#endif /* BUS_H */ diff --git a/src/cntlr.c b/src/cntlr.c index 976471e2..729527af 100644 --- a/src/cntlr.c +++ b/src/cntlr.c @@ -40,7 +40,8 @@ #include "config.h" #include "cntlr.h" #include "allsta.h" -#include "cntlr_ubus.h" +#include "cntlr_ubus.h" /* deprecate */ +#include "bus.h" #include "cntlr_map.h" #include "cntlr_cmdu.h" #include "steer_module.h" diff --git a/src/cntlr_map.c b/src/cntlr_map.c index 61f86348..c5f86732 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -45,6 +45,7 @@ #include "config.h" #include "cntlr.h" #include "cntlr_ubus.h" +#include "bus.h" #include "cntlr_map_debug.h" #include "cntlr_cmdu.h" diff --git a/src/cntlr_ubus.c b/src/cntlr_ubus.c index 8df2e53f..809985a4 100644 --- a/src/cntlr_ubus.c +++ b/src/cntlr_ubus.c @@ -39,7 +39,8 @@ #include "cntlr.h" #include "allsta.h" #include "cntlr_map.h" -#include "cntlr_ubus.h" +#include "cntlr_ubus.h" /* deprecate */ +#include "bus.h" #include "cntlr_tlv.h" #include "cntlr_tlv.h" @@ -2905,19 +2906,6 @@ static int cntlr_cac_term(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -void bus_notify_event(void *bus, void *event, void *extra) -{ - struct blob_buf b; - - memset(&b, 0, sizeof(struct blob_buf)); - blob_buf_init(&b, 0); - if (extra) - blobmsg_add_json_from_string(&b, (char *)extra); - - ubus_send_event(bus, (char *)event, b.head); - blob_buf_free(&b); -} - int cntlr_comb_metrics(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) @@ -3154,42 +3142,6 @@ out: return ret; } -/* tmo_msecs: 0 = immediate */ -int bus_wait_for_object_timeout(void *bus, void *object, uint32_t tmo_msecs, - void *res) -{ - uint32_t tmo = tmo_msecs * 1000; - uint32_t dur = 0; - uint32_t obj; - - - *((uint32_t *)res) = 0; - do { - int ret; - - usleep(dur); - ret = ubus_lookup_id(bus, (char *)object, &obj); - if (!ret) { - *((uint32_t *)res) = obj; - return 0; - } - - if (!tmo) - return -1; - - if (tmo >= 1000000) { - dur = 1000000; - tmo -= 1000000; - } else { - dur = tmo; - tmo = 0; - } - - trace("%s not up, retry after %u ms\n", (char *)object, dur / 1000); - } while (dur > 0); - - return -1; -} static void ieee1905_cb_get_almac(void *userdata, char *resp, size_t len) { @@ -3230,243 +3182,3 @@ int cntlr_get_ieee1905_almac(struct controller *c, uint8_t *almac) return ret; } - -char *bus_strerror(int num, char *string, size_t len) -{ - if (!string || !len) - return (char *)ubus_strerror(num); - - return strncpy(string, ubus_strerror(num), len); -} - -struct ubus_notifier { - char *event; - void *priv; - void (*user_cb)(void *priv, void *event, void *extra); - struct ubus_event_handler evh; - void (*ubus_cb)(struct ubus_context *ctx, - struct ubus_event_handler *ev, - const char *type, - struct blob_attr *m); -}; - -static void ubus_object_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, - const char *type, struct blob_attr *msg) -{ - struct ubus_notifier *n = container_of(ev, struct ubus_notifier, evh); - char *str; - - str = blobmsg_format_json(msg, true); - if (!str) { - dbg("%s: received event not json formatted!\n", __func__); - return; - } - free(str); - - if (!strcmp(type, "ubus.object.add") || !strcmp(type, "ubus.object.remove")) { - struct blob_attr *tb[2]; - char path[64] = {0}; - uint32_t id = 0; - static const struct blobmsg_policy attrs[2] = { - [0] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, - [1] = { .name = "path", .type = BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(attrs, 2, tb, blob_data(msg), blob_len(msg)); - if (!tb[0] || !tb[1]) - return; - - strncpy(path, blobmsg_data(tb[1]), sizeof(path) - 1); - id = (uint32_t) blobmsg_get_u32(tb[0]); - UNUSED(id); - - if (!strncmp(path, n->event, strlen(n->event))) { - if (n->user_cb) { - if (!strcmp(type, "ubus.object.add")) - n->user_cb(n->priv, "OBJECT_AVAILABLE", NULL); - else - n->user_cb(n->priv, "OBJECT_UNAVAILABLE", NULL); - } - } - } -} - -int bus_register_object_notifier(void *bus, void *object, - void (*cb)(void *userdata, void *event, void *extra), - void *userdata, void **notifier) -{ - struct ubus_notifier *t = calloc(1, sizeof(*t)); - int ret; - - if (!t) - return -1; - - t->evh.cb = ubus_object_cb; - t->event = strdup((char *)object); - t->priv = userdata; - t->user_cb = cb; - - ret = ubus_register_event_handler(bus, &t->evh, "ubus.object.*"); - if (ret) { - dbg("%s: err = %s\n", __func__, ubus_strerror(ret)); - free(t); - } - - *notifier = ret ? NULL : t; - return ret; -} - -void bus_unregister_notifier(void *bus, void *notifier) -{ - struct ubus_notifier *t = (struct ubus_notifier *)notifier; - - if (!bus || !notifier) - return; - - ubus_unregister_event_handler(bus, &t->evh); - free(t->event); - free(t); -} - -static void ubus_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, - const char *type, struct blob_attr *msg) -{ - struct ubus_notifier *n = container_of(ev, struct ubus_notifier, evh); - char *str; - - str = blobmsg_format_json(msg, true); - if (!str) { - dbg("%s: received event not json formatted!\n", __func__); - return; - } - - if (!strncmp(type, n->event, strlen(n->event))) { - struct blob_attr *tb[2]; - char path[64] = {0}; - uint32_t id = 0; - static const struct blobmsg_policy attrs[2] = { - [0] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, - [1] = { .name = "path", .type = BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(attrs, 2, tb, blob_data(msg), blob_len(msg)); - if (!tb[0] || !tb[1]) - return; - - strncpy(path, blobmsg_data(tb[1]), sizeof(path) - 1); - id = (uint32_t) blobmsg_get_u32(tb[0]); - UNUSED(id); - - if (!strncmp(path, n->event, strlen(n->event))) { - if (n->user_cb) - n->user_cb(n->priv, n->event, str); - } - } - - free(str); -} - -int bus_register_event_notifier(void *bus, void *event, - void (*cb)(void *userdata, void *event, void *extra), - void *userdata, void **notifier) -{ - struct ubus_notifier *t = calloc(1, sizeof(*t)); - int ret; - - if (!t) - return -1; - - t->ubus_cb = ubus_event_cb; - t->evh.cb = t->ubus_cb; - t->event = strdup((char *)event); - t->priv = userdata; - t->user_cb = cb; - - ret = ubus_register_event_handler(bus, &t->evh, t->event); - if (ret) { - dbg("%s: err = %s\n", __func__, ubus_strerror(ret)); - free(t); - } - - *notifier = ret ? NULL : t; - return ret; -} - -struct ubus_caller_context { - void *data; - void (*cb)(void *data, char *resp, size_t len); -}; - -static void ubus_call_object_cb(struct ubus_request *r, int type, struct blob_attr *msg) -{ - struct ubus_caller_context *uc = r->priv; - struct json_object *jobj = NULL; - char *str; - - if (!msg || !uc) { - err("%s: msg or passed context is NULL\n", __func__); - return; - } - - str = blobmsg_format_json(msg, true); - if (str) { - jobj = json_tokener_parse(str); - if (jobj) { - json_object_put(jobj); - if (uc->cb) - uc->cb(uc->data, str, strlen(str) + 1); - } - free(str); - } -} - -int bus_call_object(void *bus, void *object, void *function, - void *request, size_t len, - void (*cb)(void *userdata, char *response, size_t len), - void *userdata, uint32_t timeout) -{ - struct blob_buf bb = {0}; - struct ubus_caller_context *uc; - int ret; - - - if (!bus || !object || !function) - return -1; - - uc = calloc(1, sizeof(*uc)); - if (!uc) - return -1; - - uc->data = userdata; - uc->cb = cb; - - blob_buf_init(&bb, 0); - if (len && request && ((char *)request)[len] == '\0') { - bool res; - - res = blobmsg_add_json_from_string(&bb, request); - if (!res) { - err("%s: 'invalid request format'\n", __func__); - free(uc); - return -1; - } - } - - ret = ubus_invoke(bus, *(uint32_t *)object, (char *)function, bb.head, - ubus_call_object_cb, uc, timeout); - if (ret) { - char *str; - - err("%s: err = '%s'(%d)\n", __func__, ubus_strerror(ret), ret); - str = blobmsg_format_json(bb.head, true); - if (str) { - fprintf(stderr, "%s: arg: '%s'\n\n\n", __func__, str); - free(str); - } - } - - blob_buf_free(&bb); - free(uc); - return ret; -} - diff --git a/src/cntlr_ubus.h b/src/cntlr_ubus.h index 2276054f..34d2210b 100644 --- a/src/cntlr_ubus.h +++ b/src/cntlr_ubus.h @@ -10,37 +10,13 @@ #ifndef CNTLR_UBUS_H #define CNTLR_UBUS_H -void bus_notify_event(void *bus, void *event, void *extra); extern int cntlr_publish_object(struct controller *c, const char *objname); extern void cntlr_remove_object(struct controller *c); extern int cntlr_register_module(struct controller *c); - -int bus_call_object(void *bus, void *object, void *function, - void *request, size_t len, - void (*cb)(void *userdata, char *response, size_t len), - void *userdata, uint32_t timeout); - - -int bus_wait_for_object_timeout(void *bus, void *object, uint32_t tmo_msecs, void *res); - int ieee1905_buildcmdu_linkmetric_resp(struct controller *c, uint16_t msg_type); int cntlr_get_ieee1905_almac(struct controller *c, uint8_t *almac); - -int bus_register_object_notifier(void *bus, void *object, - void (*cb)(void *userdata, void *event, void *extra), - void *userdata, void **notifier); - -void bus_unregister_notifier(void *bus, void *notifier); - - -int bus_register_event_notifier(void *bus, void *event, - void (*cb)(void *userdata, void *event, void *extra), - void *userdata, void **notifier); - -char *bus_strerror(int num, char *string, size_t len); - #endif /* CNTLR_UBUS_H */ diff --git a/src/ubus.c b/src/ubus.c new file mode 100644 index 00000000..d7f58ac3 --- /dev/null +++ b/src/ubus.c @@ -0,0 +1,320 @@ +/* + * ubus.c - ubus implementation of bus apis + * + * Copyright (C) 2019-2022 IOPSYS Software Solutions AB. All rights reserved. + * + * Author: anjan.chanda@iopsys.eu + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <libubox/blobmsg.h> +#include <libubox/blobmsg_json.h> +#include <libubox/uloop.h> +#include <libubox/ustream.h> +#include <libubox/utils.h> +#include <libubus.h> + +#include <easy/easy.h> +#include <timer_impl.h> + +#include "utils/utils.h" +#include "utils/debug.h" +#include "bus.h" + +void bus_notify_event(void *bus, void *event, void *extra) +{ + struct blob_buf b; + + memset(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + if (extra) + blobmsg_add_json_from_string(&b, (char *)extra); + + ubus_send_event(bus, (char *)event, b.head); + blob_buf_free(&b); +} + +/* tmo_msecs: 0 = immediate, i.e. one lookup, no retry */ +int bus_wait_for_object_timeout(void *bus, void *object, uint32_t tmo_msecs, + void *res) +{ + uint32_t tmo = tmo_msecs * 1000; + uint32_t dur = 0; + uint32_t obj; + + + *((uint32_t *)res) = 0; + do { + int ret; + + usleep(dur); + ret = ubus_lookup_id(bus, (char *)object, &obj); + if (!ret) { + *((uint32_t *)res) = obj; + return 0; + } + + if (!tmo) + return -1; + + if (tmo >= 1000000) { + dur = 1000000; + tmo -= 1000000; + } else { + dur = tmo; + tmo = 0; + } + + trace("%s not up, retry after %u ms\n", (char *)object, dur / 1000); + } while (dur > 0); + + return -1; +} + +char *bus_strerror(int num, char *string, size_t len) +{ + if (!string || !len) + return (char *)ubus_strerror(num); + + return strncpy(string, ubus_strerror(num), len); +} + +struct ubus_notifier { + char *event; + void *priv; + void (*user_cb)(void *priv, void *event, void *extra); + struct ubus_event_handler evh; + void (*ubus_cb)(struct ubus_context *ctx, + struct ubus_event_handler *ev, + const char *type, + struct blob_attr *m); +}; + +static void ubus_object_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, + const char *type, struct blob_attr *msg) +{ + struct ubus_notifier *n = container_of(ev, struct ubus_notifier, evh); + char *str; + + str = blobmsg_format_json(msg, true); + if (!str) { + dbg("%s: received event not json formatted!\n", __func__); + return; + } + free(str); + + if (!strcmp(type, "ubus.object.add") || !strcmp(type, "ubus.object.remove")) { + struct blob_attr *tb[2]; + char path[64] = {0}; + uint32_t id = 0; + static const struct blobmsg_policy attrs[2] = { + [0] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, + [1] = { .name = "path", .type = BLOBMSG_TYPE_STRING } + }; + + blobmsg_parse(attrs, 2, tb, blob_data(msg), blob_len(msg)); + if (!tb[0] || !tb[1]) + return; + + strncpy(path, blobmsg_data(tb[1]), sizeof(path) - 1); + id = (uint32_t) blobmsg_get_u32(tb[0]); + UNUSED(id); + + if (!strncmp(path, n->event, strlen(n->event))) { + if (n->user_cb) { + if (!strcmp(type, "ubus.object.add")) + n->user_cb(n->priv, "OBJECT_AVAILABLE", NULL); + else + n->user_cb(n->priv, "OBJECT_UNAVAILABLE", NULL); + } + } + } +} + +int bus_register_object_notifier(void *bus, void *object, + void (*cb)(void *userdata, void *event, void *extra), + void *userdata, void **notifier) +{ + struct ubus_notifier *t = calloc(1, sizeof(*t)); + int ret; + + if (!t) + return -1; + + t->evh.cb = ubus_object_cb; + t->event = strdup((char *)object); + t->priv = userdata; + t->user_cb = cb; + + ret = ubus_register_event_handler(bus, &t->evh, "ubus.object.*"); + if (ret) { + dbg("%s: err = %s\n", __func__, ubus_strerror(ret)); + free(t); + } + + *notifier = ret ? NULL : t; + return ret; +} + +void bus_unregister_notifier(void *bus, void *notifier) +{ + struct ubus_notifier *t = (struct ubus_notifier *)notifier; + + if (!bus || !notifier) + return; + + ubus_unregister_event_handler(bus, &t->evh); + free(t->event); + free(t); +} + +static void ubus_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, + const char *type, struct blob_attr *msg) +{ + struct ubus_notifier *n = container_of(ev, struct ubus_notifier, evh); + char *str; + + str = blobmsg_format_json(msg, true); + if (!str) { + dbg("%s: received event not json formatted!\n", __func__); + return; + } + + if (!strncmp(type, n->event, strlen(n->event))) { + struct blob_attr *tb[2]; + char path[64] = {0}; + uint32_t id = 0; + static const struct blobmsg_policy attrs[2] = { + [0] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, + [1] = { .name = "path", .type = BLOBMSG_TYPE_STRING } + }; + + blobmsg_parse(attrs, 2, tb, blob_data(msg), blob_len(msg)); + if (!tb[0] || !tb[1]) + return; + + strncpy(path, blobmsg_data(tb[1]), sizeof(path) - 1); + id = (uint32_t) blobmsg_get_u32(tb[0]); + UNUSED(id); + + if (!strncmp(path, n->event, strlen(n->event))) { + if (n->user_cb) + n->user_cb(n->priv, n->event, str); + } + } + + free(str); +} + +int bus_register_event_notifier(void *bus, void *event, + void (*cb)(void *userdata, void *event, void *extra), + void *userdata, void **notifier) +{ + struct ubus_notifier *t = calloc(1, sizeof(*t)); + int ret; + + if (!t) + return -1; + + t->ubus_cb = ubus_event_cb; + t->evh.cb = t->ubus_cb; + t->event = strdup((char *)event); + t->priv = userdata; + t->user_cb = cb; + + ret = ubus_register_event_handler(bus, &t->evh, t->event); + if (ret) { + dbg("%s: err = %s\n", __func__, ubus_strerror(ret)); + free(t); + } + + *notifier = ret ? NULL : t; + return ret; +} + +struct ubus_caller_context { + void *data; + void (*cb)(void *data, char *resp, size_t len); +}; + +static void ubus_call_object_cb(struct ubus_request *r, int type, struct blob_attr *msg) +{ + struct ubus_caller_context *uc = r->priv; + struct json_object *jobj = NULL; + char *str; + + if (!msg || !uc) { + err("%s: msg or passed context is NULL\n", __func__); + return; + } + + str = blobmsg_format_json(msg, true); + if (str) { + jobj = json_tokener_parse(str); + if (jobj) { + json_object_put(jobj); + if (uc->cb) + uc->cb(uc->data, str, strlen(str) + 1); + } + free(str); + } +} + +int bus_call_object(void *bus, void *object, void *function, + void *request, size_t len, + void (*cb)(void *userdata, char *response, size_t len), + void *userdata, uint32_t timeout) +{ + struct blob_buf bb = {0}; + struct ubus_caller_context *uc; + int ret; + + + if (!bus || !object || !function) + return -1; + + uc = calloc(1, sizeof(*uc)); + if (!uc) + return -1; + + uc->data = userdata; + uc->cb = cb; + + blob_buf_init(&bb, 0); + if (len && request && ((char *)request)[len] == '\0') { + bool res; + + res = blobmsg_add_json_from_string(&bb, request); + if (!res) { + err("%s: 'invalid request format'\n", __func__); + free(uc); + return -1; + } + } + + ret = ubus_invoke(bus, *(uint32_t *)object, (char *)function, bb.head, + ubus_call_object_cb, uc, timeout); + if (ret) { + char *str; + + err("%s: err = '%s'(%d)\n", __func__, ubus_strerror(ret), ret); + str = blobmsg_format_json(bb.head, true); + if (str) { + fprintf(stderr, "%s: arg: '%s'\n\n\n", __func__, str); + free(str); + } + } + + blob_buf_free(&bb); + free(uc); + return ret; +} + -- GitLab