Formatting

This commit is contained in:
Pim van Pelt
2018-04-17 15:00:29 +02:00
parent 8bf7b919cc
commit 491ba88d1a
25 changed files with 2290 additions and 1956 deletions

View File

@ -14,6 +14,7 @@ extern "C" {
#if MGOS_ENABLE_UPDATER
bool mgos_ota_http_server_init(void);
#endif
#ifdef __cplusplus

View File

@ -16,104 +16,119 @@
#include "mgos_utils.h"
static void handle_update_post(struct mg_connection *c, int ev, void *p) {
struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *) p;
struct update_context *ctx = (struct update_context *) c->user_data;
if (ctx == NULL && ev != MG_EV_HTTP_MULTIPART_REQUEST) return;
struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *)p;
struct update_context * ctx = (struct update_context *)c->user_data;
if (ctx == NULL && ev != MG_EV_HTTP_MULTIPART_REQUEST) {
return;
}
switch (ev) {
case MG_EV_HTTP_MULTIPART_REQUEST: {
ctx = updater_context_create();
if (ctx != NULL) {
ctx->nc = c;
c->user_data = ctx;
} else {
c->flags |= MG_F_CLOSE_IMMEDIATELY;
}
break;
case MG_EV_HTTP_MULTIPART_REQUEST: {
ctx = updater_context_create();
if (ctx != NULL) {
ctx->nc = c;
c->user_data = ctx;
} else {
c->flags |= MG_F_CLOSE_IMMEDIATELY;
}
case MG_EV_HTTP_PART_BEGIN: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_BEGIN: %p %s %s", ctx, mp->var_name,
mp->file_name));
/* We use ctx->file_name as a temp buffer for non-file variable values. */
if (mp->file_name[0] == '\0') {
ctx->file_name[0] = '\0';
}
break;
}
case MG_EV_HTTP_PART_DATA: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_DATA: %p %s %s %d", ctx, mp->var_name,
mp->file_name, (int) mp->data.len));
break;
}
if (mp->file_name[0] == '\0') {
/* It's a non-file form variable. */
size_t l = strlen(ctx->file_name);
size_t avail = sizeof(ctx->file_name) - l - 1;
strncat(ctx->file_name, mp->data.p, MIN(mp->data.len, avail));
break;
} else if (!is_update_finished(ctx)) {
updater_process(ctx, mp->data.p, mp->data.len);
LOG(LL_DEBUG, ("updater_process res: %d", ctx->result));
} else {
/* Don't close connection just yet, not all browsers like that. */
}
case MG_EV_HTTP_PART_BEGIN: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_BEGIN: %p %s %s", ctx, mp->var_name,
mp->file_name));
/* We use ctx->file_name as a temp buffer for non-file variable values. */
if (mp->file_name[0] == '\0') {
ctx->file_name[0] = '\0';
}
break;
}
case MG_EV_HTTP_PART_DATA: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_DATA: %p %s %s %d", ctx, mp->var_name,
mp->file_name, (int)mp->data.len));
if (mp->file_name[0] == '\0') {
/* It's a non-file form variable. */
size_t l = strlen(ctx->file_name);
size_t avail = sizeof(ctx->file_name) - l - 1;
strncat(ctx->file_name, mp->data.p, MIN(mp->data.len, avail));
break;
} else if (!is_update_finished(ctx)) {
updater_process(ctx, mp->data.p, mp->data.len);
LOG(LL_DEBUG, ("updater_process res: %d", ctx->result));
} else {
/* Don't close connection just yet, not all browsers like that. */
}
break;
}
case MG_EV_HTTP_PART_END: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_END: %p %s %s %d", ctx, mp->var_name,
mp->file_name, mp->status));
/* Part finished with an error. REQUEST_END will follow. */
if (mp->status < 0) {
break;
}
case MG_EV_HTTP_PART_END: {
LOG(LL_DEBUG, ("MG_EV_HTTP_PART_END: %p %s %s %d", ctx, mp->var_name,
mp->file_name, mp->status));
/* Part finished with an error. REQUEST_END will follow. */
if (mp->status < 0) break;
if (mp->file_name[0] == '\0') {
/* It's a non-file form variable. Value is in ctx->file_name. */
LOG(LL_DEBUG, ("Got var: %s=%s", mp->var_name, ctx->file_name));
/* Commit timeout can be set after flashing. */
if (strcmp(mp->var_name, "commit_timeout") == 0) {
ctx->fctx.commit_timeout = atoi(ctx->file_name);
}
} else {
/* End of the fw part, but there may still be parts with vars to follow,
* which can modify settings (that can be applied post-flashing). */
if (mp->file_name[0] == '\0') {
/* It's a non-file form variable. Value is in ctx->file_name. */
LOG(LL_DEBUG, ("Got var: %s=%s", mp->var_name, ctx->file_name));
/* Commit timeout can be set after flashing. */
if (strcmp(mp->var_name, "commit_timeout") == 0) {
ctx->fctx.commit_timeout = atoi(ctx->file_name);
}
} else {
/* End of the fw part, but there may still be parts with vars to follow,
* which can modify settings (that can be applied post-flashing). */
}
break;
}
case MG_EV_HTTP_MULTIPART_REQUEST_END: {
LOG(LL_DEBUG,
("MG_EV_HTTP_MULTIPART_REQUEST_END: %p %d", ctx, mp->status));
/* Whatever happens, this is the last thing we do. */
c->flags |= MG_F_SEND_AND_CLOSE;
if (ctx == NULL) {
break;
}
case MG_EV_HTTP_MULTIPART_REQUEST_END: {
LOG(LL_DEBUG,
("MG_EV_HTTP_MULTIPART_REQUEST_END: %p %d", ctx, mp->status));
/* Whatever happens, this is the last thing we do. */
if (is_write_finished(ctx)) {
updater_finalize(ctx);
}
if (!is_update_finished(ctx)) {
ctx->result = -1;
ctx->status_msg = "Update aborted";
updater_finish(ctx);
}
if (mp->status < 0) {
/* mp->status < 0 means connection is dead, do not send reply */
} else {
int code = (ctx->result > 0 ? 200 : 400);
mg_send_response_line(c, code,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "%s\r\n",
ctx->status_msg ? ctx->status_msg : "Unknown error");
if (is_reboot_required(ctx)) {
LOG(LL_INFO, ("Rebooting device"));
mgos_system_restart_after(101);
}
c->flags |= MG_F_SEND_AND_CLOSE;
if (ctx == NULL) break;
if (is_write_finished(ctx)) updater_finalize(ctx);
if (!is_update_finished(ctx)) {
ctx->result = -1;
ctx->status_msg = "Update aborted";
updater_finish(ctx);
}
if (mp->status < 0) {
/* mp->status < 0 means connection is dead, do not send reply */
} else {
int code = (ctx->result > 0 ? 200 : 400);
mg_send_response_line(c, code,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "%s\r\n",
ctx->status_msg ? ctx->status_msg : "Unknown error");
if (is_reboot_required(ctx)) {
LOG(LL_INFO, ("Rebooting device"));
mgos_system_restart_after(101);
}
c->flags |= MG_F_SEND_AND_CLOSE;
}
updater_context_free(ctx);
c->user_data = NULL;
break;
}
updater_context_free(ctx);
c->user_data = NULL;
break;
}
}
}
struct mg_connection *s_update_request_conn;
static void mgos_ota_result_cb(struct update_context *ctx) {
if (ctx != updater_context_get_current()) return;
if (ctx != updater_context_get_current()) {
return;
}
if (s_update_request_conn != NULL) {
int code = (ctx->result > 0 ? 200 : 500);
mg_send_response_line(s_update_request_conn, code,
@ -122,112 +137,117 @@ static void mgos_ota_result_cb(struct update_context *ctx) {
mg_printf(s_update_request_conn, "(%d) %s\r\n", ctx->result,
ctx->status_msg);
s_update_request_conn->flags |= MG_F_SEND_AND_CLOSE;
s_update_request_conn = NULL;
s_update_request_conn = NULL;
}
}
static void update_handler(struct mg_connection *c, int ev, void *ev_data,
void *user_data) {
switch (ev) {
case MG_EV_HTTP_MULTIPART_REQUEST:
case MG_EV_HTTP_PART_BEGIN:
case MG_EV_HTTP_PART_DATA:
case MG_EV_HTTP_PART_END:
case MG_EV_HTTP_MULTIPART_REQUEST_END: {
if (mgos_sys_config_get_update_enable_post()) {
handle_update_post(c, ev, ev_data);
} else {
mg_send_response_line(c, 400,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "POST updates are disabled.");
c->flags |= MG_F_SEND_AND_CLOSE;
}
case MG_EV_HTTP_MULTIPART_REQUEST:
case MG_EV_HTTP_PART_BEGIN:
case MG_EV_HTTP_PART_DATA:
case MG_EV_HTTP_PART_END:
case MG_EV_HTTP_MULTIPART_REQUEST_END: {
if (mgos_sys_config_get_update_enable_post()) {
handle_update_post(c, ev, ev_data);
} else {
mg_send_response_line(c, 400,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "POST updates are disabled.");
c->flags |= MG_F_SEND_AND_CLOSE;
}
return;
}
case MG_EV_HTTP_REQUEST: {
struct http_message *hm = (struct http_message *)ev_data;
if (updater_context_get_current() != NULL) {
mg_send_response_line(c, 409,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Another update is in progress.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
return;
}
case MG_EV_HTTP_REQUEST: {
struct http_message *hm = (struct http_message *) ev_data;
if (updater_context_get_current() != NULL) {
const struct mgos_config_update *mcu = mgos_sys_config_get_update();
char * url = mcu->url;
int commit_timeout = mcu->commit_timeout;
bool ignore_same_version = true;
struct mg_str params =
(mg_vcmp(&hm->method, "POST") == 0 ? hm->body : hm->query_string);
size_t buf_len = params.len;
char * buf = calloc(params.len, 1), *p = buf;
int len = mg_get_http_var(&params, "url", p, buf_len);
if (len > 0) {
url = p;
p += len + 1;
buf_len -= len + 1;
}
len = mg_get_http_var(&params, "commit_timeout", p, buf_len);
if (len > 0) {
commit_timeout = atoi(p);
}
len = mg_get_http_var(&params, "ignore_same_version", p, buf_len);
if (len > 0) {
ignore_same_version = (atoi(p) > 0);
}
if (url != NULL) {
s_update_request_conn = c;
struct update_context *ctx = updater_context_create();
if (ctx == NULL) {
mg_send_response_line(c, 409,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Another update is in progress.\r\n");
mg_printf(c, "Failed to create updater context.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
return;
}
const struct mgos_config_update *mcu = mgos_sys_config_get_update();
char *url = mcu->url;
int commit_timeout = mcu->commit_timeout;
bool ignore_same_version = true;
struct mg_str params =
(mg_vcmp(&hm->method, "POST") == 0 ? hm->body : hm->query_string);
size_t buf_len = params.len;
char *buf = calloc(params.len, 1), *p = buf;
int len = mg_get_http_var(&params, "url", p, buf_len);
if (len > 0) {
url = p;
p += len + 1;
buf_len -= len + 1;
}
len = mg_get_http_var(&params, "commit_timeout", p, buf_len);
if (len > 0) {
commit_timeout = atoi(p);
}
len = mg_get_http_var(&params, "ignore_same_version", p, buf_len);
if (len > 0) {
ignore_same_version = (atoi(p) > 0);
}
if (url != NULL) {
s_update_request_conn = c;
struct update_context *ctx = updater_context_create();
if (ctx == NULL) {
mg_send_response_line(c, 409,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Failed to create updater context.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
return;
}
ctx->ignore_same_version = ignore_same_version;
ctx->fctx.commit_timeout = commit_timeout;
ctx->result_cb = mgos_ota_result_cb;
mgos_ota_http_start(ctx, url);
} else {
mg_send_response_line(c, 400,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Update URL not specified and none is configured.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
}
free(buf);
break;
}
case MG_EV_CLOSE: {
if (s_update_request_conn == c) {
/* Client went away while waiting for response. */
s_update_request_conn = NULL;
}
break;
ctx->ignore_same_version = ignore_same_version;
ctx->fctx.commit_timeout = commit_timeout;
ctx->result_cb = mgos_ota_result_cb;
mgos_ota_http_start(ctx, url);
} else {
mg_send_response_line(c, 400,
"Content-Type: text/plain\r\n"
"Connection: close\r\n");
mg_printf(c, "Update URL not specified and none is configured.\r\n");
c->flags |= MG_F_SEND_AND_CLOSE;
}
free(buf);
break;
}
(void) user_data;
case MG_EV_CLOSE: {
if (s_update_request_conn == c) {
/* Client went away while waiting for response. */
s_update_request_conn = NULL;
}
break;
}
}
(void)user_data;
}
static void update_action_handler(struct mg_connection *c, int ev, void *p,
void *user_data) {
if (ev != MG_EV_HTTP_REQUEST) return;
struct http_message *hm = (struct http_message *) p;
bool is_commit = (mg_vcmp(&hm->uri, "/update/commit") == 0);
if (ev != MG_EV_HTTP_REQUEST) {
return;
}
struct http_message *hm = (struct http_message *)p;
bool is_commit = (mg_vcmp(&hm->uri, "/update/commit") == 0);
bool ok =
(is_commit ? mgos_upd_commit() : mgos_upd_revert(false /* reboot */));
(is_commit ? mgos_upd_commit() : mgos_upd_revert(false /* reboot */));
mg_send_response_line(c, (ok ? 200 : 400),
"Content-Type: text/html\r\n"
"Connection: close");
mg_printf(c, "\r\n%s\r\n", (ok ? "Ok" : "Error"));
c->flags |= MG_F_SEND_AND_CLOSE;
if (ok && !is_commit) mgos_system_restart_after(100);
(void) user_data;
if (ok && !is_commit) {
mgos_system_restart_after(100);
}
(void)user_data;
}
bool mgos_ota_http_server_init(void) {