@@ -362,8 +362,8 @@ include $(srctree)/Makefile.flags
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults to vmlinux, but the arch makefile usually adds further targets
-objs-y := core handlers bootloader
-libs-y := corelib mongoose parser suricatta fs
+objs-y := core handlers bootloader suricatta
+libs-y := corelib mongoose parser fs
bindings-y := bindings
tools-y := tools
@@ -16,17 +16,7 @@
* Cf. `server_hawkbit.c` for an example implementation targeted towards the
* [hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) server.
*/
-
-extern server_op_res_t server_has_pending_action(int *action_id);
-extern server_op_res_t server_install_update(void);
-extern server_op_res_t server_send_target_data(void);
-extern unsigned int server_get_polling_interval(void);
-extern server_op_res_t server_start(const char *cfgfname, int argc, char *argv[]);
-extern server_op_res_t server_stop(void);
-extern server_op_res_t server_ipc(ipc_message *msg);
-extern void server_print_help(void);
-
-static struct server_t {
+typedef struct {
server_op_res_t (*has_pending_action)(int *action_id);
server_op_res_t (*install_update)(void);
server_op_res_t (*send_target_data)(void);
@@ -35,12 +25,6 @@ static struct server_t {
server_op_res_t (*stop)(void);
server_op_res_t (*ipc)(ipc_message *msg);
void (*help)(void);
-} server = {.has_pending_action = &server_has_pending_action,
- .install_update = &server_install_update,
- .send_target_data = &server_send_target_data,
- .get_polling_interval = &server_get_polling_interval,
- .start = &server_start,
- .stop = &server_stop,
- .ipc = &server_ipc,
- .help = &server_print_help,
-};
+} server_t;
+
+bool register_server(const char *name, server_t *server);
@@ -5,6 +5,7 @@
menuconfig SURICATTA
bool "Suricatta"
depends on HAVE_LIBCURL
+ select CHANNEL_CURL
help
Suricatta is a daemon mode of SWUpdate.
@@ -34,17 +35,10 @@ endmenu
menu "Server"
-choice
- prompt "Server Type"
- default SURICATTA_HAWKBIT
- help
- Choose the server type. Currently, just hawkBit is
- supported.
-
config SURICATTA_HAWKBIT
bool "hawkBit support"
+ default y
depends on HAVE_JSON_C
- select CHANNEL_CURL
select JSON
help
Support for hawkBit server.
@@ -55,9 +49,10 @@ comment "hawkBit support needs json-c"
config SURICATTA_LUA
bool "Suricatta Lua module"
- depends on HAVE_LIBCURL
depends on HAVE_LUA
- select CHANNEL_CURL
+ depends on HAVE_JSON_C
+ select LUA
+ select JSON
help
Support for Suricatta modules in Lua.
@@ -65,7 +60,10 @@ config SURICATTA_LUA
provides JSON as Lua Tables to the Lua realm and
enables channel result parsing to JSON per default.
To enable, select 'libjson' in 'Parser Features'.
-
+
+comment "Suricatta Lua module support needs Lua and json-c"
+ depends on !HAVE_LUA || !HAVE_JSON_C
+
config EMBEDDED_SURICATTA_LUA
bool "Embed Suricatta Lua module in SWUpdate binary"
depends on SURICATTA_LUA
@@ -90,23 +88,17 @@ config EMBEDDED_SURICATTA_LUA_SOURCE
Path to the Suricatta Lua module source code file to
be embedded into the SWUpdate binary.
-comment "Suricatta Lua module support needs libcurl and Lua"
- depends on !HAVE_LIBCURL || !HAVE_LUA
-
-comment "Suricatta Lua module JSON support needs json-c"
- depends on SURICATTA_LUA && !JSON
-
config SURICATTA_GENERAL
bool "General HTTP support"
depends on HAVE_JSON_C
- select CHANNEL_CURL
select JSON
help
Support for Simple HTTP coded server
The server uses HTTP return codes to detect if an update
is available. See documentation for more details.
-endchoice
+comment "General HTTP support needs json-c"
+ depends on !HAVE_JSON_C
endmenu
@@ -1,11 +1,14 @@
# Copyright (C) 2014-2018 Stefano Babic <sbabic@denx.de>
#
# SPDX-License-Identifier: GPL-2.0-only
-lib-$(CONFIG_SURICATTA) += suricatta.o common.o
+obj-$(CONFIG_SURICATTA) += suricatta.o common.o
ifneq ($(CONFIG_SURICATTA_HAWKBIT),)
-lib-$(CONFIG_SURICATTA) += server_hawkbit.o
+obj-$(CONFIG_SURICATTA) += server_hawkbit.o
endif
ifneq ($(CONFIG_SURICATTA_LUA),)
-lib-$(CONFIG_SURICATTA) += server_lua.o
+obj-$(CONFIG_SURICATTA) += server_lua.o
endif
-lib-$(CONFIG_SURICATTA_GENERAL) += server_general.o
+ifneq ($(CONFIG_SURICATTA_GENERAL),)
+obj-$(CONFIG_SURICATTA_GENERAL) += server_general.o
+endif
+
@@ -30,9 +30,50 @@ static bool trigger = false;
static struct option long_options[] = {
{"enable", no_argument, NULL, 'e'},
{"disable", no_argument, NULL, 'd'},
+ {"server", required_argument, NULL, 'S'},
{NULL, 0, NULL, 0}};
static sem_t suricatta_enable_sema;
+typedef struct {
+ const char *name;
+ server_t *funcs;
+} server_entry;
+
+static int servers_count = 0;
+static server_entry *servers = NULL;
+static server_t *server = NULL;
+
+bool register_server(const char *name, server_t *srv)
+{
+ if (!name || !srv) {
+ return false;
+ }
+ server_entry *tmp = realloc(servers,
+ (servers_count + 1) * sizeof(server_entry));
+ if (!tmp) {
+ return false;
+ }
+ tmp[servers_count].name = name;
+ tmp[servers_count].funcs = srv;
+ servers_count++;
+ servers = tmp;
+ return true;
+}
+
+static bool set_server(const char *name)
+{
+ if (!name || !strlen(name)) {
+ return false;
+ }
+ for (unsigned int i = 0; i < servers_count; i++) {
+ if (strcmp(name, servers[i].name) == 0) {
+ server = servers[i].funcs;
+ return true;
+ }
+ }
+ return false;
+}
+
void suricatta_print_help(void)
{
fprintf(
@@ -40,8 +81,17 @@ void suricatta_print_help(void)
"\tsuricatta arguments (mandatory arguments are marked with '*'):\n"
"\t -e, --enable Daemon enabled at startup (default).\n"
"\t -d, --disable Daemon disabled at startup.\n"
+ "\t -S, --server Suricatta module to run.\n"
);
- server.help();
+ if (servers_count == 0) {
+ fprintf(stdout, "\tNo compiled-in suricatta modules!\n");
+ return;
+ }
+ for (unsigned int i = 0; i < servers_count; i++) {
+ fprintf(stdout, "\tOptions for suricatta module '%s':\n",
+ servers[i].name);
+ (servers[i].funcs)->help();
+ }
}
static server_op_res_t suricatta_enable(ipc_message *msg)
@@ -103,7 +153,7 @@ static server_op_res_t suricatta_ipc(int fd)
result = suricatta_enable(&msg);
break;
default:
- result = server.ipc(&msg);
+ result = server->ipc(&msg);
break;
}
@@ -120,6 +170,12 @@ static int suricatta_settings(void *elem, void __attribute__ ((__unused__)) *da
get_field(LIBCFG_PARSER, elem, "enable",
&enable);
+ char cfg_server[128];
+ GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "server", cfg_server);
+ if (strlen(cfg_server) && set_server(cfg_server)) {
+ TRACE("Suricatta module '%s' selected by configuration file.", cfg_server);
+ }
+
return 0;
}
@@ -227,9 +283,16 @@ int start_suricatta(const char *cfgfname, int argc, char *argv[])
optind = 1;
opterr = 0;
- while ((choice = getopt_long(argc, argv, "de",
+ while ((choice = getopt_long(argc, argv, "deS:",
long_options, NULL)) != -1) {
switch (choice) {
+ case 'S':
+ if (!set_server(optarg)) {
+ ERROR("Suricatta module '%s' not registered.", optarg);
+ exit(EXIT_FAILURE);
+ }
+ TRACE("Suricatta module '%s' selected by command line option.", optarg);
+ break;
case 'e':
enable = true;
break;
@@ -240,6 +303,25 @@ int start_suricatta(const char *cfgfname, int argc, char *argv[])
break;
}
}
+ if (!server) {
+ if (servers_count == 0) {
+ ERROR("No compiled-in suricatta modules!");
+ exit(EXIT_FAILURE);
+ }
+ if (servers_count == 1) {
+ if (!set_server(servers[0].name)) {
+ ERROR("Internal Error: One suricatta module "
+ "available but not found?!");
+ exit(EXIT_FAILURE);
+ }
+ TRACE("Default suricatta module '%s' selected.", servers[0].name);
+
+ } else {
+ ERROR("Multiple suricatta modules available but none "
+ "selected. See swupdate --help for options.");
+ exit(EXIT_FAILURE);
+ }
+ }
if (sem_init(&suricatta_enable_sema, 0, 0)) {
ERROR("Initialising suricatta enable semaphore failed");
@@ -254,7 +336,7 @@ int start_suricatta(const char *cfgfname, int argc, char *argv[])
/*
* Now start a specific implementation of the server
*/
- if (server.start(cfgfname, argc, serverargv) != SERVER_OK) {
+ if (server->start(cfgfname, argc, serverargv) != SERVER_OK) {
exit(EXIT_FAILURE);
}
free(serverargv);
@@ -263,13 +345,13 @@ int start_suricatta(const char *cfgfname, int argc, char *argv[])
while (true) {
if (enable || trigger) {
trigger = false;
- switch (server.has_pending_action(&action_id)) {
+ switch (server->has_pending_action(&action_id)) {
case SERVER_UPDATE_AVAILABLE:
DEBUG("About to process available update.");
- server.install_update();
+ server->install_update();
break;
case SERVER_ID_REQUESTED:
- server.send_target_data();
+ server->send_target_data();
trigger = true;
break;
case SERVER_EINIT:
@@ -281,9 +363,9 @@ int start_suricatta(const char *cfgfname, int argc, char *argv[])
}
}
- for (int wait_seconds = server.get_polling_interval();
+ for (int wait_seconds = server->get_polling_interval();
wait_seconds > 0;
- wait_seconds = min(wait_seconds, (int)server.get_polling_interval())) {
+ wait_seconds = min(wait_seconds, (int)server->get_polling_interval())) {
wait_seconds = suricatta_wait(wait_seconds);
}
Allow to compile-in multiple suricatta modules and choose one at run-time with sane fallback to a single compiled-in one. Defaults to hawkBit for backwards compatibility. This feature enables distributions to ship SWUpdate with multiple suricatta modules enabled, shifting the selection to run-time rather than compile-time. Signed-off-by: Christian Storm <christian.storm@siemens.com> --- Changes in V2: * Added "See swupdate --help for options." to fatal exit in case multiple suricatta modules are available but none selected. * Fixed Coverity false positive CID 453970 in V1's suricatta.c:328 Makefile | 4 +- include/suricatta/server.h | 24 ++------- suricatta/Config.in | 30 ++++------- suricatta/Makefile | 11 ++-- suricatta/suricatta.c | 100 +++++++++++++++++++++++++++++++++---- 5 files changed, 115 insertions(+), 54 deletions(-)