This IPC command allows sending the status of an update after the
system reboots. This is useful to know if the update was successful or
not. In addition, a custom message can be sent to the mongoose server
and displayed in the "messages" section of the web interface.
Usage:
swupdate-ipc sendtomongoose --success|--failure [--message <text>]
Signed-off-by: Tanguy Raufflet <
tanguy....@savoirfairelinux.com>
---
core/network_thread.c | 5 +++
include/network_ipc.h | 1 +
include/util.h | 1 +
mongoose/mongoose_interface.c | 41 +++++++++++++++++++-
tools/swupdate-ipc.c | 71 +++++++++++++++++++++++++++++++++++
5 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/core/network_thread.c b/core/network_thread.c
index 6d4c259a..ccfa9d87 100644
--- a/core/network_thread.c
+++ b/core/network_thread.c
@@ -629,6 +629,11 @@ void *network_thread (void *data)
} else
msg.type = NACK;
break;
+ case SWUPDATE_SYSTEM_STATUS:
+ notify(msg.data.notify.status, msg.data.notify.error,
+ SYSTEM_STATUS_MSG, msg.data.notify.msg);
+ msg.type = ACK;
+ break;
default:
msg.type = NACK;
}
diff --git a/include/network_ipc.h b/include/network_ipc.h
index 8eb64cdf..2b2d3972 100644
--- a/include/network_ipc.h
+++ b/include/network_ipc.h
@@ -40,6 +40,7 @@ typedef enum {
GET_HW_REVISION,
SET_SWUPDATE_VARS,
GET_SWUPDATE_VARS,
+ SWUPDATE_SYSTEM_STATUS,
} msgtype;
/*
diff --git a/include/util.h b/include/util.h
index d4874f64..8b8d463d 100644
--- a/include/util.h
+++ b/include/util.h
@@ -119,6 +119,7 @@ typedef enum {
typedef enum {
CANCELUPDATE=LASTLOGLEVEL + 1,
CHANGE,
+ SYSTEM_STATUS_MSG,
} NOTIFY_CAUSE;
enum {
diff --git a/mongoose/mongoose_interface.c b/mongoose/mongoose_interface.c
index 729862e6..9970d803 100644
--- a/mongoose/mongoose_interface.c
+++ b/mongoose/mongoose_interface.c
@@ -70,9 +70,16 @@ struct parent_connection_info {
unsigned long id;
};
+struct system_status_state {
+ bool valid;
+ RECOVERY_STATUS status;
+ char message[256];
+};
+
static struct parent_connection_info conn_info = {0};
static bool run_postupdate;
static unsigned int watchdog_conn = 0;
+static struct system_status_state last_system_status = {0};
static struct mg_http_serve_opts s_http_server_opts;
const char *global_auth_domain;
const char *global_auth_file;
@@ -408,7 +415,24 @@ static void *broadcast_message_thread(void __attribute__ ((__unused__)) *data)
if (ret != sizeof(msg))
break;
- if (strlen(msg.data.notify.msg) != 0 &&
+ if (msg.data.notify.level == SYSTEM_STATUS_MSG) {
+ char str[512];
+ char escaped_msg[sizeof(str)];
+ last_system_status.valid = true;
+ last_system_status.status = msg.data.notify.status;
+ strncpy(last_system_status.message, msg.data.notify.msg,
+ sizeof(last_system_status.message) - 1);
+ snescape(escaped_msg, sizeof(escaped_msg), last_system_status.message);
+ snprintf(str, sizeof(str),
+ "{\r\n"
+ "\t\"type\": \"system_status\",\r\n"
+ "\t\"status\": \"%s\",\r\n"
+ "\t\"message\": \"%s\"\r\n"
+ "}\r\n",
+ last_system_status.status == SUCCESS ? "SUCCESS" : "FAILURE",
+ escaped_msg);
+ broadcast(str);
+ } else if (strlen(msg.data.notify.msg) != 0 &&
msg.data.status.current != PROGRESS) {
char text[4096];
char str[4160];
@@ -727,6 +751,21 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
#endif
} else if (ev == MG_EV_ERROR) {
ERROR("%p %s", nc->fd, (char *) ev_data);
+ } else if (ev == MG_EV_WS_OPEN) {
+ if (last_system_status.valid) {
+ char str[512];
+ char escaped_msg[sizeof(str)];
+ snescape(escaped_msg, sizeof(escaped_msg), last_system_status.message);
+ int len = snprintf(str, sizeof(str),
+ "{\r\n"
+ "\t\"type\": \"system_status\",\r\n"
+ "\t\"status\": \"%s\",\r\n"
+ "\t\"message\": \"%s\"\r\n"
+ "}\r\n",
+ last_system_status.status == SUCCESS ? "SUCCESS" : "FAILURE",
+ escaped_msg);
+ mg_ws_send(nc, str, len, WEBSOCKET_OP_TEXT);
+ }
} else if (ev == MG_EV_WS_MSG) {
mg_iobuf_del(&nc->recv, 0, nc->recv.len);
} else if (ev == MG_EV_WAKEUP) {
diff --git a/tools/swupdate-ipc.c b/tools/swupdate-ipc.c
index f3738193..03892e57 100644
--- a/tools/swupdate-ipc.c
+++ b/tools/swupdate-ipc.c
@@ -72,6 +72,15 @@ static void usage_send_to_hawkbit(const char *program) {
}
+static void usage_sendtomongoose(const char *program) {
+ fprintf(stdout, "\t %s --success|--failure [--message <text>]\n", program);
+ fprintf(stdout,
+ "\t\t--success : report a successful post-reboot system update\n"
+ "\t\t--failure : report a failed post-reboot system update\n"
+ "\t\t--message <text> : optional status message, truncated at 255 chars (default: empty)\n"
+ );
+}
+
static void usage_sysrestart(const char *programname)
{
fprintf(stdout, "\t %s [OPTION]\n", programname);
@@ -762,6 +771,67 @@ static int monitor(cmd_t __attribute__((__unused__)) *cmd, int argc, char *argv
return 0;
}
+static struct option sendtomongoose_options[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"success", no_argument, NULL, 's'},
+ {"failure", no_argument, NULL, 'f'},
+ {"message", required_argument, NULL, 'm'},
+ {NULL, 0, NULL, 0}
+};
+
+static int sendtomongoose(cmd_t __attribute__((__unused__)) *cmd, int argc, char *argv[]) {
+ ipc_message msg;
+ int c;
+ bool has_status = false;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.type = SWUPDATE_SYSTEM_STATUS;
+
+ while ((c = getopt_long(argc, argv, "sfm:h",
+ sendtomongoose_options, NULL)) != EOF) {
+ switch (c) {
+ case 's':
+ msg.data.notify.status = SUCCESS;
+ has_status = true;
+ break;
+ case 'f':
+ msg.data.notify.status = FAILURE;
+ has_status = true;
+ break;
+ case 'm':
+ strncpy(msg.data.notify.msg, optarg,
+ sizeof(msg.data.notify.msg) - 1);
+ break;
+ case 'h':
+ usage_sendtomongoose(argv[0]);
+ return 0;
+ default:
+ usage_sendtomongoose(argv[0]);
+ return 1;
+ }
+ }
+
+ if (!has_status) {
+ fprintf(stderr, "Error: --success or --failure is required\n");
+ usage_sendtomongoose(argv[0]);
+ return 1;
+ }
+
+ RECOVERY_STATUS requested_status = msg.data.notify.status;
+ int rc = ipc_send_cmd(&msg);
+ if (rc) {
+ fprintf(stderr, "Failed to send status (rc=%d)\n", rc);
+ return 1;
+ }
+ if (msg.type != ACK) {
+ fprintf(stderr, "Server returned NACK\n");
+ return 1;
+ }
+ fprintf(stdout, "System status '%s' sent to the mongoose server\n",
+ requested_status == SUCCESS ? "SUCCESS" : "FAILURE");
+ return 0;
+}
+
/*
* List of implemented commands
*/
@@ -769,6 +839,7 @@ cmd_t commands[] = {
{"aes", sendaes, usage_aes},
{"setversion",setversions, usage_setversion},
{"sendtohawkbit", sendtohawkbit, usage_send_to_hawkbit},
+ {"sendtomongoose", sendtomongoose, usage_sendtomongoose},
{"hawkbitcfg", hawkbitcfg, usage_hawkbitcfg},
{"gethawkbit", gethawkbitstatus, usage_gethawkbitstatus},
{"sysrestart", sysrestart, usage_sysrestart},
--
2.53.0