Commit 69c56691 authored by Gerson Fernando Budke's avatar Gerson Fernando Budke Committed by Anas Nashif
Browse files

lib: updatehub: Add download block check

The current CoAP implementation not perform any checks including
duplicated packets. This add block sequency verification and a
timer to ensures that slow networks works apropriately.

Signed-off-by: default avatarGerson Fernando Budke <gerson.budke@ossystems.com.br>
parent 29f883a7
Loading
Loading
Loading
Loading
+1 −0
Changes for lib/updatehub/CMakeLists.txt: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -9,4 +9,5 @@ zephyr_library()
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_device.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_firmware.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_timer.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB_SHELL shell.c)
+8 −0
Changes for lib/updatehub/Kconfig: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -86,6 +86,14 @@ config UPDATEHUB_DTLS
	  Enables DTLS communication between the UpdateHub
	  client and the server

config UPDATEHUB_COAP_CONN_TIMEOUT
	int "CoAP connection timeout in seconds"
	default 10
	range 1 360
	depends on UPDATEHUB
	help
	  Set the CoAP connection timeout value.

config UPDATEHUB_COAP_MAX_RETRY
	int "Maximum retries attempts to download a packet"
	default 10
+57 −10
Changes for lib/updatehub/updatehub.c: 57 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ LOG_MODULE_REGISTER(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);
#include "updatehub_priv.h"
#include "updatehub_firmware.h"
#include "updatehub_device.h"
#include "updatehub_timer.h"

#if defined(CONFIG_UPDATEHUB_DTLS)
#define CA_CERTIFICATE_TAG 1
@@ -363,6 +364,29 @@ static bool install_update_cb_sha256(void)
	return true;
}

static int install_update_cb_check_blk_num(struct coap_packet *resp)
{
	int blk_num;
	int blk2_opt;

	blk2_opt = coap_get_option_int(resp, COAP_OPTION_BLOCK2);

	if ((resp->max_len - resp->offset) <= 0 || (blk2_opt < 0)) {
		LOG_DBG("Invalid data received or block number is < 0");
		return -ENOENT;
	}

	blk_num = GET_BLOCK_NUM(blk2_opt);

	if (blk_num == updatehub_blk_get(UPDATEHUB_BLK_INDEX)) {
		updatehub_blk_inc(UPDATEHUB_BLK_INDEX);

		return 0;
	}

	return -EAGAIN;
}

static void install_update_cb(void)
{
	struct coap_packet response_packet;
@@ -390,6 +414,15 @@ static void install_update_cb(void)
		goto cleanup;
	}

	if (install_update_cb_check_blk_num(&response_packet) < 0) {
		ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR;
		goto cleanup;
	}

	updatehub_tmr_stop();
	updatehub_blk_set(UPDATEHUB_BLK_ATTEMPT, 0);
	updatehub_blk_set(UPDATEHUB_BLK_TX_AVAILABLE, 1);

	ctx.downloaded_size = ctx.downloaded_size +
			      (response_packet.max_len - response_packet.offset);

@@ -438,9 +471,6 @@ cleanup:

static enum updatehub_response install_update(void)
{
	int verification_download = 0;
	int attempts_download = 0;

	if (boot_erase_img_bank(FLASH_AREA_ID(image_1)) != 0) {
		LOG_ERR("Failed to init flash and erase second slot");
		ctx.code_status = UPDATEHUB_FLASH_INIT_ERROR;
@@ -469,31 +499,43 @@ static enum updatehub_response install_update(void)
	flash_img_init(&ctx.flash_ctx);

	ctx.downloaded_size = 0;
	updatehub_blk_set(UPDATEHUB_BLK_ATTEMPT, 0);
	updatehub_blk_set(UPDATEHUB_BLK_INDEX, 0);
	updatehub_blk_set(UPDATEHUB_BLK_TX_AVAILABLE, 1);

	while (ctx.downloaded_size != ctx.block.total_size) {
		verification_download = ctx.downloaded_size;

		if (updatehub_blk_get(UPDATEHUB_BLK_TX_AVAILABLE)) {
			if (send_request(COAP_TYPE_CON, COAP_METHOD_GET,
					 UPDATEHUB_DOWNLOAD) < 0) {
				ctx.code_status = UPDATEHUB_NETWORKING_ERROR;
				goto cleanup;
			}

			updatehub_blk_set(UPDATEHUB_BLK_TX_AVAILABLE, 0);
			updatehub_blk_inc(UPDATEHUB_BLK_ATTEMPT);
			updatehub_tmr_start();
		}

		install_update_cb();

		if (ctx.code_status != UPDATEHUB_OK) {
		if (ctx.code_status == UPDATEHUB_OK) {
			continue;
		}

		if (ctx.code_status != UPDATEHUB_DOWNLOAD_ERROR &&
		    ctx.code_status != UPDATEHUB_NETWORKING_ERROR) {
			LOG_DBG("status: %d", ctx.code_status);
			goto cleanup;
		}

		if (verification_download == ctx.downloaded_size) {
			if (attempts_download ==
		if (updatehub_blk_get(UPDATEHUB_BLK_ATTEMPT) ==
		    CONFIG_UPDATEHUB_COAP_MAX_RETRY) {
			updatehub_tmr_stop();

			LOG_ERR("Could not get the packet");
			ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR;
			goto cleanup;
		}
			attempts_download++;
		}
	}

cleanup:
@@ -719,6 +761,9 @@ enum updatehub_response updatehub_probe(void)
		goto cleanup;
	}

	LOG_DBG("metadata size: %d", strlen(metadata));
	LOG_HEXDUMP_DBG(metadata, MAX_DOWNLOAD_DATA, "metadata");

	memcpy(metadata_copy, metadata, strlen(metadata));
	if (json_obj_parse(metadata, strlen(metadata),
			   recv_probe_sh_array_descr,
@@ -753,6 +798,7 @@ enum updatehub_response updatehub_probe(void)
		       metadata_any_boards.objects[1].objects.sha256sum,
		       SHA256_HEX_DIGEST_SIZE);
		update_info.image_size = metadata_any_boards.objects[1].objects.size;
		LOG_DBG("metadata_any: %s", update_info.sha256sum_image);
	} else {
		if (metadata_some_boards.objects_len != 2) {
			LOG_ERR("Could not parse json");
@@ -781,6 +827,7 @@ enum updatehub_response updatehub_probe(void)
		       SHA256_HEX_DIGEST_SIZE);
		update_info.image_size =
			metadata_some_boards.objects[1].objects.size;
		LOG_DBG("metadata_some: %s", update_info.sha256sum_image);
	}

	ctx.code_status = UPDATEHUB_HAS_UPDATE;
+53 −0
Changes for lib/updatehub/updatehub_timer.c: 53 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020 O.S.Systems
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <logging/log.h>
LOG_MODULE_DECLARE(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);

#include <zephyr.h>
#include "updatehub_timer.h"

static int blk_vars[UPDATEHUB_BLK_MAX_VARS];

static void timer_expire(struct k_timer *timer)
{
	LOG_DBG("tmr_expire");
	blk_vars[UPDATEHUB_BLK_TX_AVAILABLE] = 1;
}

K_TIMER_DEFINE(uhu_packet_down_tmr, timer_expire, NULL);

int updatehub_blk_get(enum updatehub_blk_vars var)
{
	LOG_DBG("blk_get[%d] = %d", var, blk_vars[var]);
	return blk_vars[var];
}

void updatehub_blk_inc(enum updatehub_blk_vars var)
{
	blk_vars[var]++;
	LOG_DBG("blk_inc[%d] = %d", var, blk_vars[var]);
}

void updatehub_blk_set(enum updatehub_blk_vars var, int val)
{
	LOG_DBG("blk_set[%d] = %d", var, val);
	blk_vars[var] = val;
}

void updatehub_tmr_start(void)
{
	LOG_DBG("tmr_start");
	k_timer_start(&uhu_packet_down_tmr,
		      K_SECONDS(CONFIG_UPDATEHUB_COAP_CONN_TIMEOUT),
		      K_NO_WAIT);
}

void updatehub_tmr_stop(void)
{
	LOG_DBG("tmr_stop");
	k_timer_stop(&uhu_packet_down_tmr);
}
+25 −0
Changes for lib/updatehub/updatehub_timer.h: 25 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020 O.S.Systems
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef __UPDATEHUB_TIMER_H__
#define __UPDATEHUB_TIMER_H__

enum updatehub_blk_vars {
	UPDATEHUB_BLK_ATTEMPT,
	UPDATEHUB_BLK_INDEX,
	UPDATEHUB_BLK_TX_AVAILABLE,

	UPDATEHUB_BLK_MAX_VARS,
};

int updatehub_blk_get(enum updatehub_blk_vars var);
void updatehub_blk_inc(enum updatehub_blk_vars var);
void updatehub_blk_set(enum updatehub_blk_vars var, int val);

void updatehub_tmr_start(void);
void updatehub_tmr_stop(void);

#endif /* __UPDATEHUB_TIMER_H__ */