@@ -130,6 +130,7 @@ void swupdate_progress_init(unsigned int nsteps) {
struct swupdate_progress *pprog = &progress;
pthread_mutex_lock(&pprog->lock);
+ pprog->msg.apiversion = PROGRESS_API_VERSION;
pprog->msg.nsteps = nsteps;
pprog->msg.cur_step = 0;
pprog->msg.status = START;
@@ -23,12 +23,34 @@ extern "C" {
extern char* SOCKET_PROGRESS_PATH;
+/*
+ * Versioning of API
+ * it is defined as
+ * bits 31..24 : unused, set to 0
+ * bits 23..16 : Major Version
+ * bits 15..8 : Minor version
+ * bits 7..0 : small changes not relevant for compatibility
+ *
+ * The following policy is followed:
+ * - changes in minor version mean that the API was enhanced and it has
+ * new features, but it is compatible with the older. It is suggested
+ * that clients are updated, but they still work.
+ * - changes in major mean an incompatibility and clients do not work anymore
+ */
+
+#define PROGRESS_API_MAJOR 1
+#define PROGRESS_API_MINOR 0
+#define PROGRESS_API_PATCH 0
+
+#define PROGRESS_API_VERSION ((PROGRESS_API_MAJOR & 0xFFFF) << 16 | \
+ (PROGRESS_API_MINOR & 0xFF) << 8 | \
+ (PROGRESS_API_PATCH & 0xFF))
/*
* Message sent via progress socket.
* Data is sent in LE if required.
*/
struct progress_msg {
- unsigned int magic; /* Magic Number */
+ unsigned int apiversion; /* API Version for compatibility check */
RECOVERY_STATUS status; /* Update Status (Running, Failure) */
unsigned int dwl_percent; /* % downloaded data */
unsigned long long dwl_bytes; /* total of bytes to be downloaded */
@@ -82,6 +82,13 @@ int progress_ipc_receive(int *connfd, struct progress_msg *msg) {
if (ret == -1 && (errno == EAGAIN || errno == EINTR))
return 0;
+ /*
+ * size of message can vary if the API version does not match
+ * First check it to return a correct error, else it always
+ * return -1.
+ */
+ if (ret > sizeof(msg->apiversion) && (msg->apiversion != PROGRESS_API_VERSION))
+ return -EBADMSG;
if (ret != sizeof(*msg)) {
close(*connfd);
*connfd = -1;
@@ -903,7 +903,7 @@ static void *progress_offloader_thread(void *data)
(void)pthread_mutex_lock(thread_data->lua_lock);
lua_newtable(thread_data->L);
- push_to_table(thread_data->L, "magic", message->magic);
+ push_to_table(thread_data->L, "apiversion", message->apiversion);
push_to_table(thread_data->L, "status", message->status);
push_to_table(thread_data->L, "dwl_percent", message->dwl_percent);
push_to_table(thread_data->L, "nsteps", message->nsteps);
@@ -747,10 +747,10 @@ static int monitor(cmd_t __attribute__((__unused__)) *cmd, int argc, char *argv
msg.hnd_name[sizeof(msg.hnd_name) - 1] = '\0';
msg.cur_image[sizeof(msg.cur_image) - 1] = '\0';
- fprintf(stdout, "[{ \"magic\": %d, \"status\": %u, \"dwl_percent\": %u, \"dwl_bytes\": %llu"
+ fprintf(stdout, "[{ \"apiversion\": 0x%x, \"status\": %u, \"dwl_percent\": %u, \"dwl_bytes\": %llu"
", \"nsteps\": %u, \"cur_step\": %u, \"cur_percent\": %u, \"cur_image\": \"%s\""
", \"hnd_name\": \"%s\", \"source\": %u, \"infolen\": %u }",
- msg.magic, msg.status, msg.dwl_percent,
+ msg.apiversion, msg.status, msg.dwl_percent,
msg.dwl_bytes, msg.nsteps, msg.cur_step,
msg.cur_percent, msg.cur_image, msg.hnd_name,
msg.source, msg.infolen);
It is not excluded that the message structure use to exchange messages via progress interface can be changed in future, raising compatibility issues. To check this, the unused "magic" field assumes the value for the current API version. Schema for the versioning is put into include/progress_ipc.h. The receiver (progress_ipc_receive) is changed to check for changes in the major version of the API, returning an error in that case. Signed-off-by: Stefano Babic <stefano.babic@swupdate.org> --- core/progress_thread.c | 1 + include/progress_ipc.h | 24 +++++++++++++++++++++++- ipc/progress_ipc.c | 7 +++++++ suricatta/server_lua.c | 2 +- tools/swupdate-ipc.c | 4 ++-- 5 files changed, 34 insertions(+), 4 deletions(-)