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: Gerson Fernando Budke <gerson.budke@ossystems.com.br>
This commit is contained in:
Gerson Fernando Budke 2020-05-29 01:03:24 -03:00 committed by Carles Cufí
commit 3add3d7b60
5 changed files with 151 additions and 17 deletions

View file

@ -9,4 +9,5 @@ zephyr_library()
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub.c) zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_device.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_firmware.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB updatehub_timer.c)
zephyr_library_sources_ifdef(CONFIG_UPDATEHUB_SHELL shell.c) zephyr_library_sources_ifdef(CONFIG_UPDATEHUB_SHELL shell.c)

View file

@ -86,6 +86,14 @@ config UPDATEHUB_DTLS
Enables DTLS communication between the UpdateHub Enables DTLS communication between the UpdateHub
client and the server 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 config UPDATEHUB_COAP_MAX_RETRY
int "Maximum retries attempts to download a packet" int "Maximum retries attempts to download a packet"
default 10 default 10

View file

@ -26,6 +26,7 @@ LOG_MODULE_REGISTER(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL);
#include "updatehub_priv.h" #include "updatehub_priv.h"
#include "updatehub_firmware.h" #include "updatehub_firmware.h"
#include "updatehub_device.h" #include "updatehub_device.h"
#include "updatehub_timer.h"
#if defined(CONFIG_UPDATEHUB_DTLS) #if defined(CONFIG_UPDATEHUB_DTLS)
#define CA_CERTIFICATE_TAG 1 #define CA_CERTIFICATE_TAG 1
@ -363,6 +364,29 @@ static bool install_update_cb_sha256(void)
return true; 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) static void install_update_cb(void)
{ {
struct coap_packet response_packet; struct coap_packet response_packet;
@ -390,6 +414,15 @@ static void install_update_cb(void)
goto cleanup; 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 + ctx.downloaded_size = ctx.downloaded_size +
(response_packet.max_len - response_packet.offset); (response_packet.max_len - response_packet.offset);
@ -438,9 +471,6 @@ cleanup:
static enum updatehub_response install_update(void) 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) { if (boot_erase_img_bank(FLASH_AREA_ID(image_1)) != 0) {
LOG_ERR("Failed to init flash and erase second slot"); LOG_ERR("Failed to init flash and erase second slot");
ctx.code_status = UPDATEHUB_FLASH_INIT_ERROR; ctx.code_status = UPDATEHUB_FLASH_INIT_ERROR;
@ -469,30 +499,42 @@ static enum updatehub_response install_update(void)
flash_img_init(&ctx.flash_ctx); flash_img_init(&ctx.flash_ctx);
ctx.downloaded_size = 0; 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) { 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;
}
if (send_request(COAP_TYPE_CON, COAP_METHOD_GET, updatehub_blk_set(UPDATEHUB_BLK_TX_AVAILABLE, 0);
UPDATEHUB_DOWNLOAD) < 0) { updatehub_blk_inc(UPDATEHUB_BLK_ATTEMPT);
ctx.code_status = UPDATEHUB_NETWORKING_ERROR; updatehub_tmr_start();
goto cleanup;
} }
install_update_cb(); 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; goto cleanup;
} }
if (verification_download == ctx.downloaded_size) { if (updatehub_blk_get(UPDATEHUB_BLK_ATTEMPT) ==
if (attempts_download == CONFIG_UPDATEHUB_COAP_MAX_RETRY) {
CONFIG_UPDATEHUB_COAP_MAX_RETRY) { updatehub_tmr_stop();
LOG_ERR("Could not get the packet");
ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR; LOG_ERR("Could not get the packet");
goto cleanup; ctx.code_status = UPDATEHUB_DOWNLOAD_ERROR;
} goto cleanup;
attempts_download++;
} }
} }
@ -719,6 +761,9 @@ enum updatehub_response updatehub_probe(void)
goto cleanup; goto cleanup;
} }
LOG_DBG("metadata size: %d", strlen(metadata));
LOG_HEXDUMP_DBG(metadata, MAX_DOWNLOAD_DATA, "metadata");
memcpy(metadata_copy, metadata, strlen(metadata)); memcpy(metadata_copy, metadata, strlen(metadata));
if (json_obj_parse(metadata, strlen(metadata), if (json_obj_parse(metadata, strlen(metadata),
recv_probe_sh_array_descr, recv_probe_sh_array_descr,
@ -747,6 +792,7 @@ enum updatehub_response updatehub_probe(void)
metadata_any_boards.objects[1].objects.sha256sum, metadata_any_boards.objects[1].objects.sha256sum,
SHA256_HEX_DIGEST_SIZE); SHA256_HEX_DIGEST_SIZE);
update_info.image_size = metadata_any_boards.objects[1].objects.size; update_info.image_size = metadata_any_boards.objects[1].objects.size;
LOG_DBG("metadata_any: %s", update_info.sha256sum_image);
} else { } else {
if (!is_compatible_hardware(&metadata_some_boards)) { if (!is_compatible_hardware(&metadata_some_boards)) {
LOG_ERR("Incompatible hardware"); LOG_ERR("Incompatible hardware");
@ -769,6 +815,7 @@ enum updatehub_response updatehub_probe(void)
SHA256_HEX_DIGEST_SIZE); SHA256_HEX_DIGEST_SIZE);
update_info.image_size = update_info.image_size =
metadata_some_boards.objects[1].objects.size; metadata_some_boards.objects[1].objects.size;
LOG_DBG("metadata_some: %s", update_info.sha256sum_image);
} }
ctx.code_status = UPDATEHUB_HAS_UPDATE; ctx.code_status = UPDATEHUB_HAS_UPDATE;

View file

@ -0,0 +1,53 @@
/*
* 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);
}

View file

@ -0,0 +1,25 @@
/*
* 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__ */