mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
add coredump RPC
This commit is contained in:
1 parent
278c4ca116
commit
361a70517e
6 files changed
+204
No files matched your search
+86
@@ -3642,6 +3642,59 @@ struct mg_fs mg_fs_posix = {p_stat, p_list, p_open, p_close, p_read,
|
||||
|
||||
|
||||
#if MG_ENABLE_HEALTH
|
||||
#if MG_ARCH == MG_ARCH_ESP32
|
||||
// reusable for other platforms, currently ESP32-only
|
||||
struct mg_health_coredump {
|
||||
const void *ptr;
|
||||
size_t poffset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static struct mg_health_coredump s_coredump;
|
||||
#endif
|
||||
|
||||
bool mg_health_coredump_begin(size_t *size) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32 && CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
const esp_partition_t *p = esp_partition_find_first(
|
||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
|
||||
size_t address = 0, len = 0;
|
||||
esp_err_t err = esp_core_dump_image_get(&address, &len);
|
||||
if (size == NULL || s_coredump.ptr != NULL || err != ESP_OK || p == NULL)
|
||||
return false;
|
||||
s_coredump.ptr = p;
|
||||
s_coredump.poffset = address - p->address;
|
||||
s_coredump.size = len;
|
||||
*size = len;
|
||||
return true;
|
||||
#else
|
||||
(void) size;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mg_health_coredump_read(size_t offset, void *buf, size_t *len) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32 && CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
const esp_partition_t *p = (const esp_partition_t *) s_coredump.ptr;
|
||||
if (p == NULL || offset > s_coredump.size)
|
||||
return false;
|
||||
if (*len > s_coredump.size - offset) *len = s_coredump.size - offset;
|
||||
return esp_partition_read(p, s_coredump.poffset + offset, buf, *len) == ESP_OK;
|
||||
#else
|
||||
(void) offset, (void) buf, (void) len;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mg_health_coredump_end(void) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32 && CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
bool ok = s_coredump.ptr != NULL;
|
||||
memset(&s_coredump, 0, sizeof(s_coredump));
|
||||
return ok;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// The one health record. Lives in RAM that survives a warm reset, see
|
||||
// MG_HEALTH_RAM and the .mg_health region in the linker script
|
||||
struct mg_health mg_health_record MG_HEALTH_RAM;
|
||||
@@ -7351,6 +7404,7 @@ static void mg_mdash_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
}
|
||||
mg_iobuf_free(&io);
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
mg_health_coredump_end();
|
||||
mg_mdash_conn = NULL;
|
||||
MG_INFO(("disconnected, ram %lu", 0));
|
||||
}
|
||||
@@ -7408,6 +7462,35 @@ static void mg_mdash_rpc_ota_end(struct mg_rpc_req *r) {
|
||||
// MG_ESC("percent"));
|
||||
}
|
||||
|
||||
static void rpc_coredump_begin(struct mg_rpc_req *r) {
|
||||
size_t size = 0;
|
||||
if (mg_health_coredump_begin(&size)) {
|
||||
mg_rpc_ok(r, "{%m:%llu}", MG_ESC("size"), (uint64_t) size);
|
||||
} else {
|
||||
mg_rpc_err(r, 500, "%m", MG_ESC("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_coredump_read(struct mg_rpc_req *r) {
|
||||
uint8_t buf[768];
|
||||
size_t len = sizeof(buf);
|
||||
size_t offset = (size_t) mg_json_get_long(r->frame, "$.params.offset", -1);
|
||||
if (mg_health_coredump_read(offset, buf, &len)) {
|
||||
mg_rpc_ok(r, "{%m:\"%M\"}", MG_ESC("data"), mg_print_base64,
|
||||
(int) len, buf);
|
||||
} else {
|
||||
mg_rpc_err(r, 500, "%m", MG_ESC("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_coredump_end(struct mg_rpc_req *r) {
|
||||
if (mg_health_coredump_end()) {
|
||||
mg_rpc_ok(r, "true");
|
||||
} else {
|
||||
mg_rpc_err(r, 500, "%m", MG_ESC("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void mg_mdash_init(struct mg_mgr *mgr) {
|
||||
MG_INFO(("Initialising mdash agent, key [%s]", MG_MDASH_KEY));
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("RPC.List"), mg_rpc_list, NULL);
|
||||
@@ -7415,6 +7498,9 @@ void mg_mdash_init(struct mg_mgr *mgr) {
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.Begin"), mg_mdash_rpc_ota_begin, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.Write"), mg_mdash_rpc_ota_write, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.End"), mg_mdash_rpc_ota_end, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("CoreDump.Begin"), rpc_coredump_begin, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("CoreDump.Read"), rpc_coredump_read, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("CoreDump.End"), rpc_coredump_end, NULL);
|
||||
}
|
||||
|
||||
void mg_mdash_poll(struct mg_mgr *mgr) {
|
||||
|
||||
+16
@@ -256,6 +256,7 @@ extern "C" {
|
||||
#if MG_ENABLE_HEALTH
|
||||
#include <esp_memory_utils.h>
|
||||
#include <esp_core_dump.h>
|
||||
#include <esp_partition.h>
|
||||
#endif
|
||||
|
||||
#define MG_PATH_MAX 128
|
||||
@@ -4491,6 +4492,9 @@ static inline uint16_t esp2mg(esp_reset_reason_t rr) {
|
||||
#define MG_HEALTH_INIT() mg_health_init()
|
||||
extern size_t mg_print_crash_record(mg_pfn_t, void *, va_list *);
|
||||
extern void mg_health_init(void);
|
||||
extern bool mg_health_coredump_begin(size_t *size);
|
||||
extern bool mg_health_coredump_read(size_t offset, void *buf, size_t *len);
|
||||
extern bool mg_health_coredump_end(void);
|
||||
#else
|
||||
#define MG_HEALTH_INIT()
|
||||
static inline int mg_health_reason(void) {
|
||||
@@ -4505,6 +4509,18 @@ static inline size_t mg_print_crash_record(mg_pfn_t fn, void *arg,
|
||||
(void) ap;
|
||||
return mg_xprintf(fn, arg, "{}");
|
||||
}
|
||||
static inline bool mg_health_coredump_begin(size_t *size) {
|
||||
(void) size;
|
||||
return false;
|
||||
}
|
||||
static inline bool mg_health_coredump_read(size_t offset, void *buf,
|
||||
size_t *len) {
|
||||
(void) offset, (void) buf, (void) len;
|
||||
return false;
|
||||
}
|
||||
static inline bool mg_health_coredump_end(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
// Cloud connector API to https://mdash.net - device management cloud
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#if MG_ENABLE_HEALTH
|
||||
#include <esp_memory_utils.h>
|
||||
#include <esp_core_dump.h>
|
||||
#include <esp_partition.h>
|
||||
#endif
|
||||
|
||||
#define MG_PATH_MAX 128
|
||||
|
||||
@@ -2,6 +2,59 @@
|
||||
#include "health.h"
|
||||
|
||||
#if MG_ENABLE_HEALTH
|
||||
#if MG_ARCH == MG_ARCH_ESP32
|
||||
// reusable for other platforms, currently ESP32-only
|
||||
struct mg_health_coredump {
|
||||
const void *ptr;
|
||||
size_t poffset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static struct mg_health_coredump s_coredump;
|
||||
#endif
|
||||
|
||||
bool mg_health_coredump_begin(size_t *size) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32 && CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
const esp_partition_t *p = esp_partition_find_first(
|
||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
|
||||
size_t address = 0, len = 0;
|
||||
esp_err_t err = esp_core_dump_image_get(&address, &len);
|
||||
if (size == NULL || s_coredump.ptr != NULL || err != ESP_OK || p == NULL)
|
||||
return false;
|
||||
s_coredump.ptr = p;
|
||||
s_coredump.poffset = address - p->address;
|
||||
s_coredump.size = len;
|
||||
*size = len;
|
||||
return true;
|
||||
#else
|
||||
(void) size;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mg_health_coredump_read(size_t offset, void *buf, size_t *len) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32 && CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
const esp_partition_t *p = (const esp_partition_t *) s_coredump.ptr;
|
||||
if (p == NULL || offset > s_coredump.size)
|
||||
return false;
|
||||
if (*len > s_coredump.size - offset) *len = s_coredump.size - offset;
|
||||
return esp_partition_read(p, s_coredump.poffset + offset, buf, *len) == ESP_OK;
|
||||
#else
|
||||
(void) offset, (void) buf, (void) len;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mg_health_coredump_end(void) {
|
||||
#if MG_ARCH == MG_ARCH_ESP32 && CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
bool ok = s_coredump.ptr != NULL;
|
||||
memset(&s_coredump, 0, sizeof(s_coredump));
|
||||
return ok;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// The one health record. Lives in RAM that survives a warm reset, see
|
||||
// MG_HEALTH_RAM and the .mg_health region in the linker script
|
||||
struct mg_health mg_health_record MG_HEALTH_RAM;
|
||||
|
||||
@@ -123,6 +123,9 @@ static inline uint16_t esp2mg(esp_reset_reason_t rr) {
|
||||
#define MG_HEALTH_INIT() mg_health_init()
|
||||
extern size_t mg_print_crash_record(mg_pfn_t, void *, va_list *);
|
||||
extern void mg_health_init(void);
|
||||
extern bool mg_health_coredump_begin(size_t *size);
|
||||
extern bool mg_health_coredump_read(size_t offset, void *buf, size_t *len);
|
||||
extern bool mg_health_coredump_end(void);
|
||||
#else
|
||||
#define MG_HEALTH_INIT()
|
||||
static inline int mg_health_reason(void) {
|
||||
@@ -137,5 +140,17 @@ static inline size_t mg_print_crash_record(mg_pfn_t fn, void *arg,
|
||||
(void) ap;
|
||||
return mg_xprintf(fn, arg, "{}");
|
||||
}
|
||||
static inline bool mg_health_coredump_begin(size_t *size) {
|
||||
(void) size;
|
||||
return false;
|
||||
}
|
||||
static inline bool mg_health_coredump_read(size_t offset, void *buf,
|
||||
size_t *len) {
|
||||
(void) offset, (void) buf, (void) len;
|
||||
return false;
|
||||
}
|
||||
static inline bool mg_health_coredump_end(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
+33
@@ -89,6 +89,7 @@ static void mg_mdash_fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||
}
|
||||
mg_iobuf_free(&io);
|
||||
} else if (ev == MG_EV_CLOSE) {
|
||||
mg_health_coredump_end();
|
||||
mg_mdash_conn = NULL;
|
||||
MG_INFO(("disconnected, ram %lu", 0));
|
||||
}
|
||||
@@ -146,6 +147,35 @@ static void mg_mdash_rpc_ota_end(struct mg_rpc_req *r) {
|
||||
// MG_ESC("percent"));
|
||||
}
|
||||
|
||||
static void rpc_coredump_begin(struct mg_rpc_req *r) {
|
||||
size_t size = 0;
|
||||
if (mg_health_coredump_begin(&size)) {
|
||||
mg_rpc_ok(r, "{%m:%llu}", MG_ESC("size"), (uint64_t) size);
|
||||
} else {
|
||||
mg_rpc_err(r, 500, "%m", MG_ESC("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_coredump_read(struct mg_rpc_req *r) {
|
||||
uint8_t buf[768];
|
||||
size_t len = sizeof(buf);
|
||||
size_t offset = (size_t) mg_json_get_long(r->frame, "$.params.offset", -1);
|
||||
if (mg_health_coredump_read(offset, buf, &len)) {
|
||||
mg_rpc_ok(r, "{%m:\"%M\"}", MG_ESC("data"), mg_print_base64,
|
||||
(int) len, buf);
|
||||
} else {
|
||||
mg_rpc_err(r, 500, "%m", MG_ESC("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_coredump_end(struct mg_rpc_req *r) {
|
||||
if (mg_health_coredump_end()) {
|
||||
mg_rpc_ok(r, "true");
|
||||
} else {
|
||||
mg_rpc_err(r, 500, "%m", MG_ESC("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
void mg_mdash_init(struct mg_mgr *mgr) {
|
||||
MG_INFO(("Initialising mdash agent, key [%s]", MG_MDASH_KEY));
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("RPC.List"), mg_rpc_list, NULL);
|
||||
@@ -153,6 +183,9 @@ void mg_mdash_init(struct mg_mgr *mgr) {
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.Begin"), mg_mdash_rpc_ota_begin, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.Write"), mg_mdash_rpc_ota_write, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("OTA.End"), mg_mdash_rpc_ota_end, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("CoreDump.Begin"), rpc_coredump_begin, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("CoreDump.Read"), rpc_coredump_read, NULL);
|
||||
mg_rpc_add(&mgr->rpcs, mg_str("CoreDump.End"), rpc_coredump_end, NULL);
|
||||
}
|
||||
|
||||
void mg_mdash_poll(struct mg_mgr *mgr) {
|
||||
|
||||
Reference in new issue
Block a user