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:
parent
092b962350
commit
3add3d7b60
5 changed files with 151 additions and 17 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
53
lib/updatehub/updatehub_timer.c
Normal file
53
lib/updatehub/updatehub_timer.c
Normal 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);
|
||||||
|
}
|
25
lib/updatehub/updatehub_timer.h
Normal file
25
lib/updatehub/updatehub_timer.h
Normal 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__ */
|
Loading…
Add table
Add a link
Reference in a new issue