Add (private) OTA libs
This commit is contained in:
29
libs/ota-http-client/include/mgos_ota_http_client.h
Normal file
29
libs/ota-http-client/include/mgos_ota_http_client.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* An updater implementation that fetches FW from the given URL.
|
||||
*/
|
||||
|
||||
#ifndef CS_MOS_LIBS_OTA_HTTP_CLIENT_SRC_MGOS_OTA_HTTP_CLIENT_H_
|
||||
#define CS_MOS_LIBS_OTA_HTTP_CLIENT_SRC_MGOS_OTA_HTTP_CLIENT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "mgos_updater_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if MGOS_ENABLE_UPDATER
|
||||
bool mgos_ota_http_client_init(void);
|
||||
|
||||
void mgos_ota_http_start(struct update_context *ctx, const char *url);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_MOS_LIBS_OTA_HTTP_CLIENT_SRC_MGOS_OTA_HTTP_CLIENT_H_ */
|
28
libs/ota-http-client/mos.yml
Normal file
28
libs/ota-http-client/mos.yml
Normal file
@ -0,0 +1,28 @@
|
||||
author: mongoose-os
|
||||
description: Implements Mongoose OS OTA HTTP client
|
||||
type: lib
|
||||
version: 1.18
|
||||
|
||||
sources:
|
||||
- src
|
||||
includes:
|
||||
- include
|
||||
|
||||
config_schema:
|
||||
- ["update.url", "s", {title : "Fetch updates form here"}]
|
||||
- ["update.interval", "i", {title : "Check for updates this often"}]
|
||||
|
||||
# Default CA bundle for updating from mongoose-os.com (and any other site that uses LetsEncrypt) and S3.
|
||||
- ["update.ssl_ca_file", "s", "ca.pem", {title : "TLS CA file"}]
|
||||
- ["update.ssl_client_cert_file", "s", {title: "TLS client cert file"}]
|
||||
- ["update.ssl_server_name", "s", {title : "TLS Server Name"}]
|
||||
|
||||
tags:
|
||||
- c
|
||||
- ota
|
||||
- http
|
||||
|
||||
build_vars:
|
||||
MGOS_ENABLE_UPDATER: 1
|
||||
|
||||
manifest_version: 2017-09-29
|
187
libs/ota-http-client/src/mgos_ota_http_client.c
Normal file
187
libs/ota-http-client/src/mgos_ota_http_client.c
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "mgos_ota_http_client.h"
|
||||
|
||||
#include "common/cs_dbg.h"
|
||||
#include "mgos_hal.h"
|
||||
#include "mgos_mongoose.h"
|
||||
#include "mgos_config.h"
|
||||
#include "mgos_ro_vars.h"
|
||||
#include "mgos_timers.h"
|
||||
#include "mgos_utils.h"
|
||||
|
||||
#if MGOS_ENABLE_UPDATER
|
||||
|
||||
static void fw_download_handler(struct mg_connection *c, int ev, void *p,
|
||||
void *user_data) {
|
||||
struct mbuf *io = &c->recv_mbuf;
|
||||
struct update_context *ctx = (struct update_context *) user_data;
|
||||
int res = 0;
|
||||
struct mg_str *loc;
|
||||
(void) p;
|
||||
|
||||
switch (ev) {
|
||||
case MG_EV_CONNECT: {
|
||||
int result = *((int *) p);
|
||||
if (result != 0) LOG(LL_ERROR, ("connect error: %d", result));
|
||||
break;
|
||||
}
|
||||
case MG_EV_RECV: {
|
||||
if (ctx->file_size == 0) {
|
||||
LOG(LL_DEBUG, ("Looking for HTTP header"));
|
||||
struct http_message hm;
|
||||
int parsed = mg_parse_http(io->buf, io->len, &hm, 0);
|
||||
if (parsed <= 0) {
|
||||
return;
|
||||
}
|
||||
if (hm.resp_code != 200) {
|
||||
if (hm.resp_code == 304) {
|
||||
ctx->result = 1;
|
||||
ctx->need_reboot = false;
|
||||
ctx->status_msg = "Not Modified";
|
||||
updater_finish(ctx);
|
||||
} else if ((hm.resp_code == 301 || hm.resp_code == 302) &&
|
||||
(loc = mg_get_http_header(&hm, "Location")) != NULL) {
|
||||
/* NUL-terminate the URL. Every header must be followed by \r\n,
|
||||
* so there is deifnitely space there. */
|
||||
((char *) loc->p)[loc->len] = '\0';
|
||||
/* We were told to look elsewhere. Detach update context from this
|
||||
* connection so that it doesn't get finalized when it's closed. */
|
||||
mgos_ota_http_start(ctx, loc->p);
|
||||
c->user_data = NULL;
|
||||
} else {
|
||||
ctx->result = -hm.resp_code;
|
||||
ctx->need_reboot = false;
|
||||
ctx->status_msg = "Invalid HTTP response code";
|
||||
updater_finish(ctx);
|
||||
}
|
||||
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
return;
|
||||
}
|
||||
if (hm.body.len != 0) {
|
||||
LOG(LL_DEBUG, ("HTTP header: file size: %d", (int) hm.body.len));
|
||||
if (hm.body.len == (size_t) ~0) {
|
||||
LOG(LL_ERROR, ("Invalid content-length, perhaps chunked-encoding"));
|
||||
ctx->status_msg =
|
||||
"Invalid content-length, perhaps chunked-encoding";
|
||||
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
break;
|
||||
} else {
|
||||
ctx->file_size = hm.body.len;
|
||||
}
|
||||
|
||||
mbuf_remove(io, parsed);
|
||||
}
|
||||
}
|
||||
|
||||
if (io->len != 0) {
|
||||
res = updater_process(ctx, io->buf, io->len);
|
||||
mbuf_remove(io, io->len);
|
||||
|
||||
if (res == 0) {
|
||||
if (is_write_finished(ctx)) res = updater_finalize(ctx);
|
||||
if (res == 0) {
|
||||
/* Need more data, everything is OK */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
/* Error */
|
||||
LOG(LL_ERROR, ("Update error: %d %s", ctx->result, ctx->status_msg));
|
||||
}
|
||||
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MG_EV_CLOSE: {
|
||||
if (ctx == NULL) break;
|
||||
|
||||
if (is_write_finished(ctx)) updater_finalize(ctx);
|
||||
|
||||
if (!is_update_finished(ctx)) {
|
||||
/* Update failed or connection was terminated by server */
|
||||
if (ctx->status_msg == NULL) ctx->status_msg = "Update failed";
|
||||
ctx->result = -1;
|
||||
} else if (is_reboot_required(ctx)) {
|
||||
LOG(LL_INFO, ("Rebooting device"));
|
||||
mgos_system_restart_after(100);
|
||||
}
|
||||
updater_finish(ctx);
|
||||
updater_context_free(ctx);
|
||||
c->user_data = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mgos_ota_http_start(struct update_context *ctx, const char *url) {
|
||||
LOG(LL_INFO, ("Update URL: %s, ct: %d, isv? %d", url,
|
||||
ctx->fctx.commit_timeout, ctx->ignore_same_version));
|
||||
|
||||
struct mg_connect_opts opts;
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
|
||||
#if MG_ENABLE_SSL
|
||||
if (strlen(url) > 8 && strncmp(url, "https://", 8) == 0) {
|
||||
opts.ssl_server_name = mgos_sys_config_get_update_ssl_server_name();
|
||||
opts.ssl_ca_cert = mgos_sys_config_get_update_ssl_ca_file();
|
||||
opts.ssl_cert = mgos_sys_config_get_update_ssl_client_cert_file();
|
||||
}
|
||||
#endif
|
||||
|
||||
char ehb[150];
|
||||
char *extra_headers = ehb;
|
||||
mg_asprintf(&extra_headers, sizeof(ehb),
|
||||
"X-MGOS-Device-ID: %s %s\r\n"
|
||||
"X-MGOS-FW-Version: %s %s %s\r\n",
|
||||
(mgos_sys_config_get_device_id() ? mgos_sys_config_get_device_id() : "-"),
|
||||
mgos_sys_ro_vars_get_mac_address(),
|
||||
mgos_sys_ro_vars_get_arch(),
|
||||
mgos_sys_ro_vars_get_fw_version(),
|
||||
mgos_sys_ro_vars_get_fw_id());
|
||||
|
||||
struct mg_connection *c = mg_connect_http_opt(
|
||||
mgos_get_mgr(), fw_download_handler, ctx, opts, url, extra_headers, NULL);
|
||||
|
||||
if (extra_headers != ehb) free(extra_headers);
|
||||
|
||||
if (c == NULL) {
|
||||
LOG(LL_ERROR, ("Failed to connect to %s", url));
|
||||
ctx->result = -10;
|
||||
ctx->need_reboot = false;
|
||||
ctx->status_msg = "Failed to connect";
|
||||
updater_finish(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->nc = c;
|
||||
}
|
||||
|
||||
static void mgos_ota_timer_cb(void *arg) {
|
||||
const struct mgos_config_update *mcu = mgos_sys_config_get_update();
|
||||
if (mcu->url == NULL) return;
|
||||
struct update_context *ctx = updater_context_create();
|
||||
if (ctx == NULL) return;
|
||||
ctx->ignore_same_version = true;
|
||||
ctx->fctx.commit_timeout = mcu->commit_timeout;
|
||||
mgos_ota_http_start(ctx, mcu->url);
|
||||
|
||||
(void) arg;
|
||||
}
|
||||
|
||||
bool mgos_ota_http_client_init(void) {
|
||||
const struct mgos_config_update *mcu = mgos_sys_config_get_update();
|
||||
if (mcu->url != NULL && mcu->interval > 0) {
|
||||
LOG(LL_INFO,
|
||||
("Updates from %s, every %d seconds", mcu->url, mcu->interval));
|
||||
mgos_set_timer(mcu->interval * 1000, true /* repeat */, mgos_ota_timer_cb,
|
||||
mcu->url);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* MGOS_ENABLE_UPDATER */
|
Reference in New Issue
Block a user