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_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)

View file

@ -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

View file

@ -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,
@ -747,6 +792,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 (!is_compatible_hardware(&metadata_some_boards)) {
LOG_ERR("Incompatible hardware");
@ -769,6 +815,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;

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__ */