#include "../obk_config.h"
#include "../new_common.h"
#include "../logging/logging.h"
#include "../httpserver/new_http.h"
#include "../new_pins.h"
#include "../jsmn/jsmn_h.h"
#include "../hal/hal_ota.h"
#include "../hal/hal_wifi.h"
#include "../hal/hal_flashVars.h"
#include "../littlefs/our_lfs.h"
#include "lwip/sockets.h"
#define DEFAULT_FLASH_LEN 0x200000
#if PLATFORM_RTL8710A
#undef DEFAULT_FLASH_LEN
#define DEFAULT_FLASH_LEN 0x400000
#elif PLATFORM_RTL8720D || PLATFORM_REALTEK_NEW
extern uint8_t flash_size_8720;
#undef DEFAULT_FLASH_LEN
#define DEFAULT_FLASH_LEN (flash_size_8720 << 20)
#endif
#include "../new_cfg.h"
// Commands register, execution API and cmd tokenizer
#include "../cmnds/cmd_public.h"
#ifndef OBK_DISABLE_ALL_DRIVERS
#include "../driver/drv_local.h"
#endif
#define MAX_JSON_VALUE_LENGTH 128
int http_rest_error(http_request_t* request, int code, char* msg);
static int http_rest_get(http_request_t* request);
static int http_rest_post(http_request_t* request);
static int http_rest_app(http_request_t* request);
static int http_rest_post_pins(http_request_t* request);
static int http_rest_get_pins(http_request_t* request);
static int http_rest_get_channelTypes(http_request_t* request);
static int http_rest_post_channelTypes(http_request_t* request);
static int http_rest_get_seriallog(http_request_t* request);
static int http_rest_post_logconfig(http_request_t* request);
static int http_rest_get_logconfig(http_request_t* request);
#if ENABLE_LITTLEFS
static int http_rest_get_lfs_delete(http_request_t* request);
static int http_rest_get_lfs_file(http_request_t* request);
static int http_rest_run_lfs_file(http_request_t* request);
static int http_rest_post_lfs_file(http_request_t* request);
#endif
static int http_rest_post_reboot(http_request_t* request);
int http_rest_post_flash(http_request_t* request, int startaddr, int maxaddr);
static int http_rest_get_flash(http_request_t* request, int startaddr, int len);
static int http_rest_get_flash_advanced(http_request_t* request);
static int http_rest_post_flash_advanced(http_request_t* request);
static int http_rest_get_info(http_request_t* request);
static int http_rest_post_channels(http_request_t* request);
static int http_rest_get_channels(http_request_t* request);
static int http_rest_post_cmd(http_request_t* request);
void init_rest() {
HTTP_RegisterCallback("/api/", HTTP_GET, http_rest_get, 1);
HTTP_RegisterCallback("/api/", HTTP_POST, http_rest_post, 1);
HTTP_RegisterCallback("/app", HTTP_GET, http_rest_app, 1);
}
/* Extracts string token value into outBuffer (128 char). Returns true if the operation was successful. */
bool tryGetTokenString(const char* json, jsmntok_t* tok, char* outBuffer) {
int length;
if (tok == NULL || tok->type != JSMN_STRING) {
return false;
}
length = tok->end - tok->start;
//Don't have enough buffer
if (length > MAX_JSON_VALUE_LENGTH) {
return false;
}
memset(outBuffer, '\0', MAX_JSON_VALUE_LENGTH); //Wipe previous value
strncpy(outBuffer, json + tok->start, length);
return true;
}
static int http_rest_get(http_request_t* request) {
ADDLOG_DEBUG(LOG_FEATURE_API, "GET of %s", request->url);
if (!strcmp(request->url, "api/channels")) {
return http_rest_get_channels(request);
}
if (!strcmp(request->url, "api/pins")) {
return http_rest_get_pins(request);
}
if (!strcmp(request->url, "api/channelTypes")) {
return http_rest_get_channelTypes(request);
}
if (!strcmp(request->url, "api/logconfig")) {
return http_rest_get_logconfig(request);
}
if (!strncmp(request->url, "api/seriallog", 13)) {
return http_rest_get_seriallog(request);
}
#if ENABLE_LITTLEFS
if (!strcmp(request->url, "api/fsblock")) {
uint32_t newsize = CFG_GetLFS_Size();
uint32_t newstart = (LFS_BLOCKS_END - newsize);
newsize = (newsize / LFS_BLOCK_SIZE) * LFS_BLOCK_SIZE;
// double check again that we're within bounds - don't want
// boot overwrite or anything nasty....
if (newstart < LFS_BLOCKS_START_MIN) {
return http_rest_error(request, -20, "LFS Size mismatch");
}
if ((newstart + newsize > LFS_BLOCKS_END) ||
(newstart + newsize < LFS_BLOCKS_START_MIN)) {
return http_rest_error(request, -20, "LFS Size mismatch");
}
return http_rest_get_flash(request, newstart, newsize);
}
#endif
#if ENABLE_LITTLEFS
if (!strncmp(request->url, "api/lfs/", 8)) {
return http_rest_get_lfs_file(request);
}
if (!strncmp(request->url, "api/run/", 8)) {
return http_rest_run_lfs_file(request);
}
if (!strncmp(request->url, "api/del/", 8)) {
return http_rest_get_lfs_delete(request);
}
#endif
if (!strcmp(request->url, "api/info")) {
return http_rest_get_info(request);
}
if (!strncmp(request->url, "api/flash/", 10)) {
return http_rest_get_flash_advanced(request);
}
http_setup(request, httpMimeTypeHTML);
http_html_start(request, "GET REST API");
poststr(request, "GET of ");
poststr(request, request->url);
http_html_end(request);
poststr(request, NULL);
return 0;
}
static int http_rest_post(http_request_t* request) {
char tmp[20];
ADDLOG_DEBUG(LOG_FEATURE_API, "POST to %s", request->url);
if (!strcmp(request->url, "api/channels")) {
return http_rest_post_channels(request);
}
if (!strcmp(request->url, "api/pins")) {
return http_rest_post_pins(request);
}
if (!strcmp(request->url, "api/channelTypes")) {
return http_rest_post_channelTypes(request);
}
if (!strcmp(request->url, "api/logconfig")) {
return http_rest_post_logconfig(request);
}
if (!strcmp(request->url, "api/reboot")) {
return http_rest_post_reboot(request);
}
if (!strcmp(request->url, "api/ota")) {
OTA_IncrementProgress(1);
int r = 0;
#if PLATFORM_BEKEN
r = http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA, LFS_BLOCKS_END);
#elif PLATFORM_W600
r = http_rest_post_flash(request, -1, -1);
#elif PLATFORM_W800
r = http_rest_post_flash(request, -1, -1);
#elif PLATFORM_BL602
r = http_rest_post_flash(request, -1, -1);
#elif PLATFORM_LN882H
r = http_rest_post_flash(request, -1, -1);
#elif PLATFORM_ESPIDF || PLATFORM_ESP8266
r = http_rest_post_flash(request, -1, -1);
#elif PLATFORM_REALTEK
r = http_rest_post_flash(request, 0, -1);
#elif PLATFORM_ECR6600 || PLATFORM_TR6260
r = http_rest_post_flash(request, -1, -1);
#elif PLATFORM_XRADIO && !PLATFORM_XR809
r = http_rest_post_flash(request, 0, -1);
#elif PLATFORM_TXW81X
r = http_rest_post_flash(request, 0, -1);
#elif PLATFORM_RDA5981
r = http_rest_post_flash(request, 0, -1);
#else
// TODO
ADDLOG_ERROR(LOG_FEATURE_API, "No OTA");
#endif
OTA_ResetProgress();
return r;
}
if (!strncmp(request->url, "api/flash/", 10)) {
return http_rest_post_flash_advanced(request);
}
if (!strcmp(request->url, "api/cmnd")) {
return http_rest_post_cmd(request);
}
#if ENABLE_LITTLEFS
if (!strcmp(request->url, "api/fsblock")) {
if (lfs_present()) {
release_lfs();
}
uint32_t newsize = CFG_GetLFS_Size();
uint32_t newstart = (LFS_BLOCKS_END - newsize);
newsize = (newsize / LFS_BLOCK_SIZE) * LFS_BLOCK_SIZE;
// double check again that we're within bounds - don't want
// boot overwrite or anything nasty....
if (newstart < LFS_BLOCKS_START_MIN) {
return http_rest_error(request, -20, "LFS Size mismatch");
}
if ((newstart + newsize > LFS_BLOCKS_END) ||
(newstart + newsize < LFS_BLOCKS_START_MIN)) {
return http_rest_error(request, -20, "LFS Size mismatch");
}
// we are writing the lfs block
int res = http_rest_post_flash(request, newstart, LFS_BLOCKS_END);
// initialise the filesystem, it should be there now.
// don't create if it does not mount
init_lfs(0);
return res;
}
if (!strncmp(request->url, "api/lfs/", 8)) {
return http_rest_post_lfs_file(request);
}
#endif
http_setup(request, httpMimeTypeHTML);
http_html_start(request, "POST REST API");
poststr(request, "POST to ");
poststr(request, request->url);
poststr(request, "
Content Length:");
sprintf(tmp, "%d", request->contentLength);
poststr(request, tmp);
poststr(request, "
Content:[");
poststr(request, request->bodystart);
poststr(request, "]
");
http_html_end(request);
poststr(request, NULL);
return 0;
}
static int http_rest_app(http_request_t* request) {
const char* webhost = CFG_GetWebappRoot();
const char* ourip = HAL_GetMyIPString(); //CFG_GetOurIP();
http_setup(request, httpMimeTypeHTML);
if (webhost && ourip) {
poststr(request, htmlDoctype);
poststr(request, "