Message ID | 20230509080726.23738-1-christian.storm@siemens.com |
---|---|
State | Changes Requested |
Headers | show |
Series | [1/3] suricatta: Suricatta module run-time selection | expand |
Hallo Christian, On 09.05.23 10:07, 'Christian Storm' via swupdate wrote: > 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 was definetly on the TODO list - even if most projects just selects one server, ther eare use case (not only with packaged SWUpdate) where this is useful - thanks ! > 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> > --- > Makefile | 4 +- > include/suricatta/server.h | 24 ++-------- > suricatta/Config.in | 30 +++++-------- > suricatta/Makefile | 11 +++-- > suricatta/suricatta.c | 89 ++++++++++++++++++++++++++++++++++---- > 5 files changed, 104 insertions(+), 54 deletions(-) > > diff --git a/Makefile b/Makefile > index 9f6a33a6..41abd303 100644 > --- a/Makefile > +++ b/Makefile > @@ -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 > > diff --git a/include/suricatta/server.h b/include/suricatta/server.h > index 07981df6..451211e9 100644 > --- a/include/suricatta/server.h > +++ b/include/suricatta/server.h > @@ -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); > diff --git a/suricatta/Config.in b/suricatta/Config.in > index 29dc7386..0fde4401 100644 > --- a/suricatta/Config.in > +++ b/suricatta/Config.in > @@ -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 > > diff --git a/suricatta/Makefile b/suricatta/Makefile > index 8fbb1ce9..f5b2bbdf 100644 > --- a/suricatta/Makefile > +++ b/suricatta/Makefile > @@ -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 > + > diff --git a/suricatta/suricatta.c b/suricatta/suricatta.c > index b10da933..394019f3 100644 > --- a/suricatta/suricatta.c > +++ b/suricatta/suricatta.c > @@ -30,9 +30,44 @@ 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) > +{ > + 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; > +} Ok - for me this cange is straightforward, it reuses the same method (constructor) to build up the internal list (like handlers are doing), so I do not see issues. I am expecting that some users will get an issue if they do not adjust their swupdate.cfg or command line in the startup scripts, I will note to write this in the changelog for the next release. Best regards, Stefano > + > +static bool set_server(const char *name) > +{ > + 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 +75,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 +147,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 +164,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 +277,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 +297,20 @@ 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) { > + (void)set_server(servers[0].name); > + TRACE("Default suricatta module '%s' selected.", servers[0].name); > + > + } else { > + ERROR("Multiple suricatta modules available but none selected."); > + exit(EXIT_FAILURE); > + } > + } > > if (sem_init(&suricatta_enable_sema, 0, 0)) { > ERROR("Initialising suricatta enable semaphore failed"); > @@ -254,7 +325,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 +334,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 +352,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); > } >
Hi Stefano, > > 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 was definetly on the TODO list - even if most projects just selects one > server, ther eare use case (not only with packaged SWUpdate) where this is > useful - thanks ! You're welcome! > > [...] > > diff --git a/suricatta/suricatta.c b/suricatta/suricatta.c > > index b10da933..394019f3 100644 > > --- a/suricatta/suricatta.c > > +++ b/suricatta/suricatta.c > > @@ -30,9 +30,44 @@ 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) > > +{ > > + 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; > > +} > > Ok - for me this cange is straightforward, it reuses the same method > (constructor) to build up the internal list (like handlers are doing), so I do > not see issues. I am expecting that some users will get an issue if they do > not adjust their swupdate.cfg or command line in the startup scripts, I will > note to write this in the changelog for the next release. I tried to be as conservative as possible while I thought about how to implement this... So, existing kconfig'urations have none or only one suricatta module enabled and this patch falls back to use that single built-in one if no option (configuration file or cmdline) is given ― which is the case for existing deployments, so they don't break. If you start a new kconfig'uration from scratch, hawkBit is selected as default, assuming that's the most widely used suricatta module. If you chose to build-in multiple suricatta modules, you have to select one at run-time, else SWUpdate bails out with an according error. This is new behavior but I guess OK so: I thought about also falling back to hawkBit then but this may cause confusion as well. Hence, distributions need to ship a modified/default configuration file or a default service supervisor configuration that pre-selects one. This case is indeed a good thing for a changelog and/or a heads-up for distribution packagers... Kind regards, Christian
Hi Christian, On 09.05.23 13:41, 'Christian Storm' via swupdate wrote: > Hi Stefano, > > >>> 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 was definetly on the TODO list - even if most projects just selects one >> server, ther eare use case (not only with packaged SWUpdate) where this is >> useful - thanks ! > > You're welcome! > >>> [...] >>> diff --git a/suricatta/suricatta.c b/suricatta/suricatta.c >>> index b10da933..394019f3 100644 >>> --- a/suricatta/suricatta.c >>> +++ b/suricatta/suricatta.c >>> @@ -30,9 +30,44 @@ 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) >>> +{ >>> + 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; >>> +} >> >> Ok - for me this cange is straightforward, it reuses the same method >> (constructor) to build up the internal list (like handlers are doing), so I do >> not see issues. I am expecting that some users will get an issue if they do >> not adjust their swupdate.cfg or command line in the startup scripts, I will >> note to write this in the changelog for the next release. > > I tried to be as conservative as possible while I thought about how to > implement this... > > So, existing kconfig'urations have none or only one suricatta module > enabled and this patch falls back to use that single built-in one if no > option (configuration file or cmdline) is given ― which is the case for > existing deployments, so they don't break. Yes, I find good. > > If you start a new kconfig'uration from scratch, hawkBit is selected as > default, assuming that's the most widely used suricatta module. It is ok, too. > > If you chose to build-in multiple suricatta modules, you have to select > one at run-time, else SWUpdate bails out with an according error. > This is new behavior but I guess OK so: I thought about also falling > back to hawkBit then but this may cause confusion as well. Yes, I think it is ok and it is better als falling back. > Hence, distributions need to ship a modified/default configuration file > or a default service supervisor configuration that pre-selects one. > This case is indeed a good thing for a changelog and/or a heads-up for > distribution packagers... > Best regards, Stefano > > > Kind regards, > Christian >
diff --git a/Makefile b/Makefile index 9f6a33a6..41abd303 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/include/suricatta/server.h b/include/suricatta/server.h index 07981df6..451211e9 100644 --- a/include/suricatta/server.h +++ b/include/suricatta/server.h @@ -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); diff --git a/suricatta/Config.in b/suricatta/Config.in index 29dc7386..0fde4401 100644 --- a/suricatta/Config.in +++ b/suricatta/Config.in @@ -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 diff --git a/suricatta/Makefile b/suricatta/Makefile index 8fbb1ce9..f5b2bbdf 100644 --- a/suricatta/Makefile +++ b/suricatta/Makefile @@ -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 + diff --git a/suricatta/suricatta.c b/suricatta/suricatta.c index b10da933..394019f3 100644 --- a/suricatta/suricatta.c +++ b/suricatta/suricatta.c @@ -30,9 +30,44 @@ 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) +{ + 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) +{ + 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 +75,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 +147,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 +164,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 +277,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 +297,20 @@ 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) { + (void)set_server(servers[0].name); + TRACE("Default suricatta module '%s' selected.", servers[0].name); + + } else { + ERROR("Multiple suricatta modules available but none selected."); + exit(EXIT_FAILURE); + } + } if (sem_init(&suricatta_enable_sema, 0, 0)) { ERROR("Initialising suricatta enable semaphore failed"); @@ -254,7 +325,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 +334,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 +352,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> --- Makefile | 4 +- include/suricatta/server.h | 24 ++-------- suricatta/Config.in | 30 +++++-------- suricatta/Makefile | 11 +++-- suricatta/suricatta.c | 89 ++++++++++++++++++++++++++++++++++---- 5 files changed, 104 insertions(+), 54 deletions(-)