diff mbox series

[2/3,netifd] handler: add mechanism to generate external device handler stubs

Message ID 20201210141451.224846-3-arne.kappen@hhi.fraunhofer.de
State Accepted
Headers show
Series support external device handlers | expand

Commit Message

arne.kappen@hhi.fraunhofer.de Dec. 10, 2020, 2:14 p.m. UTC
From: Arne Kappen <arne.kappen@hhi.fraunhofer.de>

Parse JSON files in a given directory and pass the information on to a callback
function for creation of an external device handler stub.
The description contains:
 - 'name': the name of the device type,
 - 'ubus_name': the name of the external device handler daemon on ubus,
 - 'bridge': a flag indicating whether the devices are bridge-like,
 - optionally 'br_prefix': a prefix for created devices
   (only for bridge-like, defaults to type name),
 - 'config': the UCI config options for devices of this type, and
 - optionally 'info' and 'stats': the format of calls to info() and dump().

Signed-off-by: Arne Kappen <arne.kappen@hhi.fraunhofer.de>
---
 handler.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 handler.h |   5 +++
 2 files changed, 119 insertions(+)
diff mbox series

Patch

diff --git a/handler.c b/handler.c
index 8608a97..04bdbee 100644
--- a/handler.c
+++ b/handler.c
@@ -78,6 +78,65 @@  netifd_init_script_handler(const char *script, json_object *obj, script_dump_cb
 	cb(script, name, obj);
 }
 
+static void
+netifd_init_extdev_handler(const char *config_file, json_object *obj,
+			   create_extdev_handler_cb cb)
+{
+	json_object *tmp, *cfg, *info, *stats;
+	const char *name, *ubus_name, *br_prefix = NULL;
+	bool bridge_support = true;
+	char *err_missing;
+
+	if (!json_check_type(obj, json_type_object))
+		return;
+
+	tmp = json_get_field(obj, "name", json_type_string);
+	if (!tmp) {
+		err_missing = "name";
+		goto field_missing;
+	}
+
+	name = json_object_get_string(tmp);
+
+	tmp = json_get_field(obj, "ubus_name", json_type_string);
+	if (!tmp) {
+		err_missing = "ubus_name";
+		goto field_missing;
+	}
+
+	ubus_name = json_object_get_string(tmp);
+
+	tmp = json_get_field(obj, "bridge", json_type_string);
+	if (!tmp || !strcmp(json_object_get_string(tmp), "0"))
+		bridge_support = false;
+
+	if (bridge_support) {
+		tmp = json_get_field(obj, "br-prefix", json_type_string);
+		if (!tmp)
+			br_prefix = name;
+		else
+			br_prefix = json_object_get_string(tmp);
+	}
+
+	tmp = json_get_field(obj, "config", json_type_array);
+	if (!tmp) {
+		err_missing = "config";
+		goto field_missing;
+	}
+
+	cfg = tmp;
+
+	info = json_get_field(obj, "info", json_type_array);
+	stats = json_get_field(obj, "stats", json_type_array);
+
+	cb(config_file, name, ubus_name, bridge_support, br_prefix, cfg, info, stats);
+	return;
+
+field_missing:
+	netifd_log_message(L_WARNING, "external device handler description '%s' is"
+			       "missing field '%s'\n", config_file, err_missing);
+}
+
 static void
 netifd_parse_script_handler(const char *name, script_dump_cb cb)
 {
@@ -125,6 +184,48 @@  netifd_parse_script_handler(const char *name, script_dump_cb cb)
 	pclose(f);
 }
 
+static void
+netifd_parse_extdev_handler(const char *path_to_file, create_extdev_handler_cb cb)
+{
+	struct json_tokener *tok = NULL;
+	json_object *obj;
+	FILE *file;
+	int len;
+	char buf[512], *start;
+
+	file = fopen(path_to_file, "r");
+	if (!file)
+		return;
+
+	do {
+		start = fgets(buf, sizeof(buf), file);
+		if (!start)
+			continue;
+
+		len = strlen(start);
+
+		if (!tok)
+			tok = json_tokener_new();
+
+		obj = json_tokener_parse_ex(tok, start, len);
+
+		if (obj) {
+			netifd_init_extdev_handler(path_to_file, obj, cb);
+			json_object_put(obj);
+			json_tokener_free(tok);
+			tok = NULL;
+		} else if (start[len - 1] == '\n') {
+			json_tokener_free(tok);
+			tok = NULL;
+		}
+	} while (!feof(file) && !ferror(file));
+
+	if (tok)
+		json_tokener_free(tok);
+
+	fclose(file);
+}
+
 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
 {
 	glob_t g;
@@ -143,6 +244,19 @@  void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
 	globfree(&g);
 }
 
+void
+netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb)
+{
+	glob_t g;
+	int prev_fd;
+
+	prev_fd = netifd_dir_push(dir_fd);
+	glob("*.json", 0, NULL, &g);
+	for (int i = 0; i < g.gl_pathc; i++)
+		netifd_parse_extdev_handler(g.gl_pathv[i], cb);
+	netifd_dir_pop(prev_fd);
+}
+
 char *
 netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj)
 {
diff --git a/handler.h b/handler.h
index e3e2af5..7064409 100644
--- a/handler.h
+++ b/handler.h
@@ -19,6 +19,10 @@ 
 #include "config.h"
 
 typedef void (*script_dump_cb)(const char *script, const char *name, json_object *obj);
+typedef void (*create_extdev_handler_cb)(const char *cfg_file, const char *name,
+					 const char *ubus_name, bool bridge,
+					 const char *br_prefix, json_object *config_obj,
+					 json_object *info_obj, json_object *stats_obj);
 
 static inline json_object *
 json_check_type(json_object *obj, json_type type)
@@ -41,6 +45,7 @@  json_get_field(json_object *obj, const char *name, json_type type)
 
 int netifd_open_subdir(const char *name);
 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb);
+void netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb);
 char *netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj);
 
 #endif