Rebase private OTA libs on 2.7

This commit is contained in:
Pim van Pelt
2018-10-28 12:12:24 +01:00
parent 497c62b382
commit 9ee393bc8a
29 changed files with 3836 additions and 521 deletions

View File

@ -1,13 +1,25 @@
/*
* Copyright (c) 2016 Cesanta Software Limited
* Copyright (c) 2014-2018 Cesanta Software Limited
* All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the ""License"");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an ""AS IS"" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mgos_rpc_service_ota.h"
#include "mg_rpc.h"
#include "mgos_rpc.h"
#include "mgos_ota_http_client.h"
#include "mgos_rpc.h"
#include "common/cs_dbg.h"
#include "common/mg_str.h"
@ -17,23 +29,29 @@
static struct mg_rpc_request_info *s_update_req;
static void mg_rpc_updater_result(struct update_context *ctx) {
if (s_update_req == NULL) {
return;
static void ota_status_cb(int ev, void *ev_data, void *userdata) {
struct mgos_ota_status *s = (struct mgos_ota_status *) ev_data;
if (s_update_req == NULL) return;
if (s->state == MGOS_OTA_STATE_ERROR) {
mg_rpc_send_errorf(s_update_req, -1, s->msg);
s_update_req = NULL;
} else if (s->state == MGOS_OTA_STATE_SUCCESS) {
mg_rpc_send_responsef(s_update_req, "true");
s_update_req = NULL;
}
mg_rpc_send_errorf(s_update_req, (ctx->result > 0 ? 0 : -1), ctx->status_msg);
s_update_req = NULL;
(void) ev;
(void) userdata;
}
static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_rpc_frame_info *fi,
struct mg_str args) {
char * blob_url = NULL;
struct json_token url_tok = JSON_INVALID_TOKEN;
int commit_timeout = 0;
char *blob_url = NULL;
struct json_token url_tok = JSON_INVALID_TOKEN;
int timeout = 0, commit_timeout = 0;
struct update_context *ctx = NULL;
LOG(LL_DEBUG, ("Update request received: %.*s", (int)args.len, args.p));
LOG(LL_DEBUG, ("Update request received: %.*s", (int) args.len, args.p));
const char *reply = "Malformed request";
@ -41,13 +59,12 @@ static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg,
goto clean;
}
json_scanf(args.p, args.len, ri->args_fmt, &url_tok, &commit_timeout);
json_scanf(args.p, args.len, ri->args_fmt, &url_tok, &timeout,
&commit_timeout);
if (url_tok.len == 0 || url_tok.type != JSON_TYPE_STRING) {
goto clean;
}
if (url_tok.len == 0 || url_tok.type != JSON_TYPE_STRING) goto clean;
LOG(LL_DEBUG, ("URL: %.*s commit_timeout: %d", url_tok.len, url_tok.ptr,
LOG(LL_DEBUG, ("URL: %.*s to: %d cto: %d", url_tok.len, url_tok.ptr, timeout,
commit_timeout));
/*
@ -63,28 +80,25 @@ static void handle_update_req(struct mg_rpc_request_info *ri, void *cb_arg,
memcpy(blob_url, url_tok.ptr, url_tok.len);
ctx = updater_context_create();
ctx = updater_context_create(timeout);
if (ctx == NULL) {
reply = "Failed to init updater";
goto clean;
}
ctx->fctx.commit_timeout = commit_timeout;
ctx->result_cb = mg_rpc_updater_result;
s_update_req = ri;
s_update_req = ri;
mgos_ota_http_start(ctx, blob_url);
free(blob_url);
return;
clean:
if (blob_url != NULL) {
free(blob_url);
}
if (blob_url != NULL) free(blob_url);
LOG(LL_ERROR, ("Failed to start update: %s", reply));
mg_rpc_send_errorf(ri, -1, reply);
ri = NULL;
(void)cb_arg;
(void)fi;
(void) cb_arg;
(void) fi;
}
static void handle_commit_req(struct mg_rpc_request_info *ri, void *cb_arg,
@ -96,9 +110,9 @@ static void handle_commit_req(struct mg_rpc_request_info *ri, void *cb_arg,
mg_rpc_send_errorf(ri, -1, NULL);
}
ri = NULL;
(void)cb_arg;
(void)fi;
(void)args;
(void) cb_arg;
(void) fi;
(void) args;
}
static void handle_revert_req(struct mg_rpc_request_info *ri, void *cb_arg,
@ -106,14 +120,14 @@ static void handle_revert_req(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_str args) {
if (mgos_upd_revert(false /* reboot */)) {
mg_rpc_send_responsef(ri, NULL);
mgos_system_restart_after(100);
mgos_system_restart_after(300);
} else {
mg_rpc_send_errorf(ri, -1, NULL);
}
ri = NULL;
(void)cb_arg;
(void)fi;
(void)args;
(void) cb_arg;
(void) fi;
(void) args;
}
static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
@ -121,32 +135,31 @@ static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
struct mg_rpc_frame_info *fi,
struct mg_str args) {
const char *err_msg = NULL;
int ret = -1;
int ret = -1;
if (mgos_upd_is_committed()) {
ret = mgos_upd_create_snapshot();
if (ret >= 0) {
bool set_as_revert = false;
int commit_timeout = -1;
bool set_as_revert = false;
int commit_timeout = -1;
json_scanf(args.p, args.len, ri->args_fmt, &set_as_revert,
&commit_timeout);
if (set_as_revert) {
struct mgos_upd_boot_state bs;
if (mgos_upd_boot_get_state(&bs)) {
bs.is_committed = false;
bs.revert_slot = ret;
bs.revert_slot = ret;
if (mgos_upd_boot_set_state(&bs)) {
if (commit_timeout >= 0 &&
!mgos_upd_set_commit_timeout(commit_timeout)) {
ret = -4;
ret = -4;
err_msg = "Failed to set commit timeout";
}
} else {
ret = -3;
ret = -3;
err_msg = "Failed to set boot state";
}
} else {
ret = -2;
ret = -2;
err_msg = "Failed to get boot state";
}
}
@ -154,7 +167,7 @@ static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
err_msg = "Failed to create snapshot";
}
} else {
ret = -1;
ret = -1;
err_msg = "Cannot create snapshots in uncommitted state";
}
if (ret >= 0) {
@ -162,8 +175,8 @@ static void handle_create_snapshot_req(struct mg_rpc_request_info *ri,
} else {
mg_rpc_send_errorf(ri, ret, err_msg);
}
(void)cb_arg;
(void)fi;
(void) cb_arg;
(void) fi;
}
static void handle_get_boot_state_req(struct mg_rpc_request_info *ri,
@ -171,7 +184,6 @@ static void handle_get_boot_state_req(struct mg_rpc_request_info *ri,
struct mg_rpc_frame_info *fi,
struct mg_str args) {
struct mgos_upd_boot_state bs;
if (!mgos_upd_boot_get_state(&bs)) {
mg_rpc_send_errorf(ri, -1, NULL);
} else {
@ -181,9 +193,9 @@ static void handle_get_boot_state_req(struct mg_rpc_request_info *ri,
bs.active_slot, bs.is_committed, bs.revert_slot,
mgos_upd_get_commit_timeout());
}
(void)cb_arg;
(void)fi;
(void)args;
(void) cb_arg;
(void) fi;
(void) args;
}
static void handle_set_boot_state_req(struct mg_rpc_request_info *ri,
@ -192,7 +204,6 @@ static void handle_set_boot_state_req(struct mg_rpc_request_info *ri,
struct mg_str args) {
int ret = 0;
struct mgos_upd_boot_state bs;
if (mgos_upd_boot_get_state(&bs)) {
int commit_timeout = -1;
if (json_scanf(args.p, args.len, ri->args_fmt, &bs.active_slot,
@ -212,28 +223,107 @@ static void handle_set_boot_state_req(struct mg_rpc_request_info *ri,
} else {
mg_rpc_send_errorf(ri, ret, NULL);
}
(void)cb_arg;
(void)fi;
(void) cb_arg;
(void) fi;
}
static void handle_status(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_rpc_frame_info *fi, struct mg_str args) {
struct mgos_ota_status s;
mgos_upd_get_status(&s);
mg_rpc_send_responsef(ri,
"{state: %d, message: %Q, is_committed: %B, "
"progress_percent: %d, commit_timeout: %d, partition: "
"%d}",
s.state, s.msg, s.is_committed, s.progress_percent,
s.commit_timeout, s.partition);
(void) args;
(void) cb_arg;
(void) fi;
}
static void handle_begin(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_rpc_frame_info *fi, struct mg_str args) {
int timeout = 0, commit_timeout = 0, size = 0;
json_scanf(args.p, args.len, ri->args_fmt, &timeout, &commit_timeout, &size);
struct update_context *ctx = updater_context_create(timeout);
if (ctx == NULL) {
mg_rpc_send_errorf(ri, -1, "Failed to init updater");
} else {
ctx->fctx.commit_timeout = commit_timeout;
ctx->zip_file_size = size;
mg_rpc_send_responsef(ri, NULL);
}
(void) cb_arg;
(void) fi;
}
static void handle_write(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_rpc_frame_info *fi, struct mg_str args) {
char *data = NULL;
int len;
struct update_context *ctx = updater_context_get_current();
if (ctx == NULL) {
mg_rpc_send_errorf(ri, -1, "Update not started");
return;
}
json_scanf(args.p, args.len, ri->args_fmt, &data, &len);
if (data == NULL) {
mg_rpc_send_errorf(ri, -1, "Data required");
} else if (updater_process(ctx, data, len) < 0) {
mg_rpc_send_errorf(ri, -1, "Write error: %s",
(ctx->status_msg ? ctx->status_msg : ""));
} else {
mg_rpc_send_responsef(ri, NULL);
}
free(data);
(void) cb_arg;
(void) fi;
}
static void handle_end(struct mg_rpc_request_info *ri, void *cb_arg,
struct mg_rpc_frame_info *fi, struct mg_str args) {
struct update_context *ctx = updater_context_get_current();
if (ctx == NULL) {
mg_rpc_send_errorf(ri, -1, "Update not started");
} else if (updater_finalize(ctx) < 0) {
mg_rpc_send_errorf(ri, -1, "Update finalize failed: %s", ctx->status_msg);
} else {
mgos_system_restart_after(500);
handle_status(ri, cb_arg, fi, args);
}
/* Finalized successfully or not, update is finished. */
if (ctx != NULL) {
updater_finish(ctx);
updater_context_free(ctx);
}
}
bool mgos_rpc_service_ota_init(void) {
struct mg_rpc *mg_rpc = mgos_rpc_get_global();
if (mg_rpc == NULL) {
return true;
}
mg_rpc_add_handler(mg_rpc, "OTA.Update", "{url: %T, commit_timeout: %d}",
if (mg_rpc == NULL) return true;
mg_rpc_add_handler(mg_rpc, "OTA.Update",
"{url: %T, timeout: %d, commit_timeout: %d}",
handle_update_req, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.Commit", "", handle_commit_req, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.Revert", "", handle_revert_req, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.CreateSnapshot",
"{set_as_revert: %B, commit_timeout: %d}",
handle_create_snapshot_req, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.Begin",
"{timeout: %d, commit_timeout: %d, size: %d}",
handle_begin, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.Write", "{data: %V}", handle_write, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.End", "", handle_end, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.Status", "", handle_status, NULL);
mg_rpc_add_handler(mg_rpc, "OTA.GetBootState", "", handle_get_boot_state_req,
NULL);
mg_rpc_add_handler(mg_rpc, "OTA.SetBootState",
"{active_slot: %d, is_committed: %B, revert_slot: %d, "
"commit_timeout: %d}",
handle_set_boot_state_req, NULL);
mgos_event_add_handler(MGOS_EVENT_OTA_STATUS, ota_status_cb, NULL);
return true;
}