From 11a12e63b3afe01067d2fa61a85f83045e902626 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 07:41:36 +0000 Subject: [PATCH 1/8] fix crash on empty content.json (NULL) --- src/contentJson.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/contentJson.c b/src/contentJson.c index 5708e112..646258ab 100644 --- a/src/contentJson.c +++ b/src/contentJson.c @@ -167,18 +167,22 @@ error_t load_content_json(const char *content_path, contentJson_t *content_json) error = ERROR_FILE_NOT_FOUND; } + if (error == NO_ERROR) + { + content_json->_valid = true; + } + if (error != NO_ERROR) { error = save_content_json(content_path, content_json); + if (error == NO_ERROR) + { + load_content_json(content_path, content_json); + } } osFreeMem(jsonPath); - if (error == NO_ERROR) - { - content_json->_valid = true; - } - return error; } From 870a53a4f36dfe8beeb27cd15beb5c29f78b9766 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 07:42:01 +0000 Subject: [PATCH 2/8] Save model for content only available on the box. --- include/contentJson.h | 1 + src/contentJson.c | 23 +++++++++++++++++++++++ src/handler.c | 21 +-------------------- src/handler_cloud.c | 4 ++++ 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/include/contentJson.h b/include/contentJson.h index 37fe6812..36ab0ace 100644 --- a/include/contentJson.h +++ b/include/contentJson.h @@ -29,4 +29,5 @@ typedef struct error_t load_content_json(const char *content_path, contentJson_t *content_json); error_t save_content_json(const char *content_path, contentJson_t *content_json); +void content_json_update_model(contentJson_t *content_json, uint32_t audio_id); void free_content_json(contentJson_t *content_json); \ No newline at end of file diff --git a/src/contentJson.c b/src/contentJson.c index 646258ab..b5059fb7 100644 --- a/src/contentJson.c +++ b/src/contentJson.c @@ -5,6 +5,7 @@ #include "cJSON.h" #include "net_config.h" #include "server_helpers.h" +#include "toniesJson.h" char *content_jsonGetString(cJSON *jsonElement, char *name) { @@ -236,6 +237,28 @@ error_t save_content_json(const char *content_path, contentJson_t *content_json) return error; } +void content_json_update_model(contentJson_t *content_json, uint32_t audio_id) +{ + toniesJson_item_t *toniesJson = tonies_byAudioId(audio_id); + if (content_json->_valid) + { + if (toniesJson != NULL && osStrcmp(content_json->tonie_model, "") == 0) + { + if (osStrcmp(content_json->tonie_model, toniesJson->model) != 0) + { + osFreeMem(content_json->tonie_model); + content_json->tonie_model = strdup(toniesJson->model); + content_json->_updated = true; + } + } + else if (toniesJson == NULL && osStrcmp(content_json->tonie_model, "") != 0) + { + // TODO add to tonies.custom.json + report + TRACE_WARNING("Audio-id %08X unknown but previous content known by model %s.\r\n", audio_id, content_json->tonie_model); + } + } +} + void free_content_json(contentJson_t *content_json) { content_json->_valid = false; diff --git a/src/handler.c b/src/handler.c index 207a1c9c..9b90ba73 100644 --- a/src/handler.c +++ b/src/handler.c @@ -1,6 +1,5 @@ #include "handler.h" #include "server_helpers.h" -#include "toniesJson.h" req_cbr_t getCloudCbr(HttpConnection *connection, const char_t *uri, const char_t *queryString, cloudapi_t api, cbr_ctx_t *ctx, client_ctx_t *client_ctx) { @@ -275,25 +274,7 @@ tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings) if (tonieInfo.tafHeader) { tonieInfo.valid = true; - toniesJson_item_t *toniesJson = tonies_byAudioId(tonieInfo.tafHeader->audio_id); - if (tonieInfo.contentConfig._valid) - { - if (toniesJson != NULL && osStrcmp(tonieInfo.contentConfig.tonie_model, "") == 0) - { - if (osStrcmp(tonieInfo.contentConfig.tonie_model, toniesJson->model) != 0) - { - osFreeMem(tonieInfo.contentConfig.tonie_model); - tonieInfo.contentConfig.tonie_model = strdup(toniesJson->model); - tonieInfo.contentConfig._updated = true; - } - } - else if (toniesJson == NULL && osStrcmp(tonieInfo.contentConfig.tonie_model, "") != 0) - { - // TODO add to tonies.custom.json + report - TRACE_WARNING("Audio-id %08X unknown but previous content known by model %s.\r\n", tonieInfo.tafHeader->audio_id, tonieInfo.contentConfig.tonie_model); - } - } - + content_json_update_model(&tonieInfo.contentConfig, tonieInfo.tafHeader->audio_id); if (tonieInfo.tafHeader->num_bytes == TONIE_LENGTH_MAX) { tonieInfo.stream = true; diff --git a/src/handler_cloud.c b/src/handler_cloud.c index a2292ca9..7ecb4f21 100644 --- a/src/handler_cloud.c +++ b/src/handler_cloud.c @@ -622,6 +622,10 @@ error_t handleCloudFreshnessCheck(HttpConnection *connection, const char_t *uri, date_buffer_server, custom_server ? ", custom" : ""); } + else + { + content_json_update_model(&tonieInfo.contentConfig, freshReq->tonie_infos[i]->audio_id); + } TRACE_INFO_RESUME("\r\n"); From ca2cf7e86e4031fb8f0fdc417c926106f14c2199 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 08:52:10 +0000 Subject: [PATCH 3/8] dump rUID/auth to content.json --- include/contentJson.h | 4 ++-- include/settings.h | 3 ++- src/contentJson.c | 7 ++++--- src/handler_cloud.c | 36 +++++++++++++++++++++++++++++++----- src/settings.c | 1 + 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/include/contentJson.h b/include/contentJson.h index 36ab0ace..ea1ae3a9 100644 --- a/include/contentJson.h +++ b/include/contentJson.h @@ -13,7 +13,7 @@ typedef struct char *cloud_ruid; uint8_t *cloud_auth; size_t cloud_auth_len; - bool_t cloud_valid; + bool_t cloud_override; char *tonie_model; bool_t _stream; @@ -25,7 +25,7 @@ typedef struct } contentJson_t; -#define CONTENT_JSON_VERSION 4 +#define CONTENT_JSON_VERSION 5 error_t load_content_json(const char *content_path, contentJson_t *content_json); error_t save_content_json(const char *content_path, contentJson_t *content_json); diff --git a/include/settings.h b/include/settings.h index 8b519f81..70396ec7 100644 --- a/include/settings.h +++ b/include/settings.h @@ -13,7 +13,7 @@ #define TONIES_CUSTOM_JSON_PATH "config/tonies.custom.json" #define CONFIG_PATH "config/config.ini" #define CONFIG_OVERLAY_PATH "config/config.overlay.ini" -#define CONFIG_VERSION 4 +#define CONFIG_VERSION 5 #define MAX_OVERLAYS 16 + 1 typedef enum @@ -58,6 +58,7 @@ typedef struct bool markCustomTagByPass; bool prioCustomContent; bool updateOnLowerAudioId; + bool dumpRuidAuthContentJson; } settings_cloud_t; typedef struct diff --git a/src/contentJson.c b/src/contentJson.c index b5059fb7..43406fce 100644 --- a/src/contentJson.c +++ b/src/contentJson.c @@ -129,18 +129,18 @@ error_t load_content_json(const char *content_path, contentJson_t *content_json) content_json->cache = content_jsonGetBool(contentJson, "cache"); content_json->cloud_ruid = content_jsonGetString(contentJson, "cloud_ruid"); content_json->cloud_auth = content_jsonGetBytes(contentJson, "cloud_auth", &content_json->cloud_auth_len); + content_json->cloud_override = content_jsonGetBool(contentJson, "cloud_override"); content_json->tonie_model = content_jsonGetString(contentJson, "tonie_model"); - content_json->cloud_valid = true; // TODO: use checkCustomTonie to validate if (osStrlen(content_json->cloud_ruid) != 16) { // TODO validate rUID - content_json->cloud_valid = false; + content_json->cloud_override = false; } if (content_json->cloud_auth_len != AUTH_TOKEN_LENGTH) { - content_json->cloud_valid = false; + content_json->cloud_override = false; } if (osStrlen(content_json->source) > 0) @@ -200,6 +200,7 @@ error_t save_content_json(const char *content_path, contentJson_t *content_json) cJSON_AddBoolToObject(contentJson, "cache", content_json->cache); content_AddStringToObject(contentJson, "cloud_ruid", content_json->cloud_ruid); content_AddByteArrayToObject(contentJson, "cloud_auth", content_json->cloud_auth, content_json->cloud_auth_len); + cJSON_AddBoolToObject(contentJson, "cloud_override", content_json->cloud_override); content_AddStringToObject(contentJson, "tonie_model", content_json->tonie_model); cJSON_AddNumberToObject(contentJson, "_version", CONTENT_JSON_VERSION); diff --git a/src/handler_cloud.c b/src/handler_cloud.c index 7ecb4f21..20bb9bf4 100644 --- a/src/handler_cloud.c +++ b/src/handler_cloud.c @@ -171,6 +171,22 @@ void markLiveTonie(tonie_info_t *tonieInfo) TRACE_INFO("Marked custom tonie %s\r\n", tonieInfo->contentPath); } +void dumpRuidAuth(contentJson_t *content_json, char *ruid, uint8_t *authentication) +{ + if (!content_json->cloud_override && osStrlen(content_json->cloud_ruid) == 0) + { + osFreeMem(content_json->cloud_auth); + content_json->cloud_auth_len = AUTH_TOKEN_LENGTH; + content_json->cloud_auth = osAllocMem(content_json->cloud_auth_len); + osMemcpy(content_json->cloud_auth, authentication, content_json->cloud_auth_len); + + osFreeMem(content_json->cloud_ruid); + content_json->cloud_ruid = strdup(ruid); + content_json->_updated = true; + TRACE_INFO("Dumped rUID %s and auth into content.json\r\n", content_json->cloud_ruid); + } +} + error_t handleCloudLog(HttpConnection *connection, const char_t *uri, const char_t *queryString, client_ctx_t *client_ctx) { if (client_ctx->settings->cloud.enabled && client_ctx->settings->cloud.enableV1Log) @@ -213,16 +229,21 @@ error_t handleCloudClaim(HttpConnection *connection, const char_t *uri, const ch httpPrepareHeader(connection, NULL, 0); connection->response.statusCode = 200; - if (!tonieInfo.contentConfig.nocloud || tonieInfo.contentConfig.cloud_valid) + if (client_ctx->settings->cloud.dumpRuidAuthContentJson) { - if (checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo.contentConfig.cloud_valid) + dumpRuidAuth(&tonieInfo.contentConfig, ruid, token); + } + + if (!tonieInfo.contentConfig.nocloud || tonieInfo.contentConfig.cloud_override) + { + if (checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo.contentConfig.cloud_override) { TRACE_INFO(" >> custom tonie detected, nothing forwarded\r\n"); markCustomTonie(&tonieInfo); } else if (client_ctx->settings->cloud.enabled && client_ctx->settings->cloud.enableV1Claim) { - if (tonieInfo.contentConfig.cloud_valid) + if (tonieInfo.contentConfig.cloud_override) { token = tonieInfo.contentConfig.cloud_auth; convertTokenBytesToString(token, msg, client_ctx->settings->log.logFullAuth); @@ -285,7 +306,7 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const getContentPathFromCharRUID(ruid, &tonieInfo.contentPath, client_ctx->settings); tonieInfo = getTonieInfo(tonieInfo.contentPath, client_ctx->settings); - if (!tonieInfo.contentConfig.nocloud && !noPassword && checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo.contentConfig.cloud_valid) + if (!tonieInfo.contentConfig.nocloud && !noPassword && checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo.contentConfig.cloud_override) { TRACE_INFO(" >> custom tonie detected, nothing forwarded\r\n"); markCustomTonie(&tonieInfo); @@ -293,6 +314,11 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const settings_t *settings = client_ctx->settings; + if (client_ctx->settings->cloud.dumpRuidAuthContentJson) + { + dumpRuidAuth(&tonieInfo.contentConfig, ruid, token); + } + bool setLive = false; const char *assignFile = NULL; @@ -446,7 +472,7 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const { TRACE_INFO("Serve cloud content from %s\r\n", uri); - if (tonieInfo.contentConfig.cloud_valid) + if (tonieInfo.contentConfig.cloud_override) { token = tonieInfo.contentConfig.cloud_auth; convertTokenBytesToString(token, msg, client_ctx->settings->log.logFullAuth); diff --git a/src/settings.c b/src/settings.c index c691fdc1..e9b442c4 100644 --- a/src/settings.c +++ b/src/settings.c @@ -167,6 +167,7 @@ static void option_map_init(uint8_t settingsId) OPTION_BOOL("cloud.markCustomTagByPass", &settings->cloud.markCustomTagByPass, TRUE, "Autodetect custom tags", "Automatically mark custom tags by password") OPTION_BOOL("cloud.prioCustomContent", &settings->cloud.prioCustomContent, TRUE, "Prioritize custom content", "Prioritize custom content over tonies content (force update)") OPTION_BOOL("cloud.updateOnLowerAudioId", &settings->cloud.updateOnLowerAudioId, FALSE, "Update content on lower audio id", "Update content on a lower audio id") + OPTION_BOOL("cloud.dumpRuidAuthContentJson", &settings->cloud.dumpRuidAuthContentJson, FALSE, "Dump rUID/auth", "Dump the rUID and authentication into the content JSON.") OPTION_TREE_DESC("toniebox", "Toniebox") OPTION_BOOL("toniebox.overrideCloud", &settings->toniebox.overrideCloud, TRUE, "Override cloud settings", "Override tonies cloud settings") From 23fee97ae9196767ea0714534c3d00ef83f36688 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 09:24:49 +0000 Subject: [PATCH 4/8] add missing override init --- src/handler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/handler.c b/src/handler.c index 9b90ba73..46fb2cf1 100644 --- a/src/handler.c +++ b/src/handler.c @@ -243,6 +243,7 @@ tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings) tonieInfo.contentConfig.cloud_ruid = NULL; tonieInfo.contentConfig.cloud_auth = NULL; tonieInfo.contentConfig.cloud_auth_len = 0; + tonieInfo.contentConfig.cloud_override = false; tonieInfo.contentConfig.tonie_model = NULL; tonieInfo.contentConfig._valid = false; From 9dfaf8b1d36900fe3dcef966cf00ab4a54e37675 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 10:28:11 +0000 Subject: [PATCH 5/8] getTonieInfo as pointer rename contentConfig to json move contentJson init to contentJson.c (fixes broken streaming) --- include/handler.h | 8 ++- src/contentJson.c | 14 +++++ src/handler.c | 92 ++++++++++++++-------------- src/handler_api.c | 18 +++--- src/handler_cloud.c | 145 ++++++++++++++++++++++---------------------- 5 files changed, 146 insertions(+), 131 deletions(-) diff --git a/include/handler.h b/include/handler.h index c0e763eb..3900554c 100644 --- a/include/handler.h +++ b/include/handler.h @@ -26,7 +26,7 @@ typedef struct bool_t valid; bool_t updated; bool_t stream; - contentJson_t contentConfig; + contentJson_t json; TonieboxAudioFileHeader *tafHeader; } tonie_info_t; @@ -67,7 +67,7 @@ typedef struct size_t bufferLen; uint32_t status; FsFile *file; - tonie_info_t tonieInfo; + tonie_info_t *tonieInfo; HttpConnection *connection; client_ctx_t *client_ctx; } cbr_ctx_t; @@ -85,7 +85,9 @@ char *strupr(char input[]); void getContentPathFromCharRUID(char ruid[17], char **pcontentPath, settings_t *settings); void getContentPathFromUID(uint64_t uid, char **pcontentPath, settings_t *settings); void setTonieboxSettings(TonieFreshnessCheckResponse *freshResp, settings_t *settings); -tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings); +tonie_info_t *getTonieInfoFromUid(uint64_t uid, settings_t *settings); +tonie_info_t *getTonieInfoFromRuid(char ruid[17], settings_t *settings); +tonie_info_t *getTonieInfo(const char *contentPath, settings_t *settings); void freeTonieInfo(tonie_info_t *tonieInfo); void httpPrepareHeader(HttpConnection *connection, const void *contentType, size_t contentLength); diff --git a/src/contentJson.c b/src/contentJson.c index 43406fce..4561c028 100644 --- a/src/contentJson.c +++ b/src/contentJson.c @@ -88,6 +88,20 @@ error_t load_content_json(const char *content_path, contentJson_t *content_json) char *jsonPath = custom_asprintf("%s.json", content_path); error_t error = NO_ERROR; osMemset(content_json, 0, sizeof(contentJson_t)); + content_json->live = false; + content_json->nocloud = false; + content_json->source = NULL; + content_json->skip_seconds = 0; + content_json->cache = false; + content_json->_updated = false; + content_json->_stream = false; + content_json->_streamFile = custom_asprintf("%s.stream", content_path); + content_json->cloud_ruid = NULL; + content_json->cloud_auth = NULL; + content_json->cloud_auth_len = 0; + content_json->cloud_override = false; + content_json->tonie_model = NULL; + content_json->_valid = false; if (fsFileExists(jsonPath)) { diff --git a/src/handler.c b/src/handler.c index 46fb2cf1..fc82b986 100644 --- a/src/handler.c +++ b/src/handler.c @@ -92,12 +92,11 @@ void cbrCloudBodyPassthrough(void *src_ctx, HttpClientContext *cloud_ctx, const char ruid[17]; osStrncpy(ruid, &ctx->uri[12], sizeof(ruid)); ruid[16] = 0; - getContentPathFromCharRUID(ruid, &ctx->tonieInfo.contentPath, ctx->client_ctx->settings); - ctx->tonieInfo = getTonieInfo(ctx->tonieInfo.contentPath, ctx->client_ctx->settings); + ctx->tonieInfo = getTonieInfoFromRuid(ruid, ctx->client_ctx->settings); - char *tmpPath = custom_asprintf("%s.tmp", ctx->tonieInfo.contentPath); + char *tmpPath = custom_asprintf("%s.tmp", ctx->tonieInfo->contentPath); - char *dir = strdup(ctx->tonieInfo.contentPath); + char *dir = strdup(ctx->tonieInfo->contentPath); dir[osStrlen(dir) - 8] = '\0'; fsCreateDir(dir); @@ -119,23 +118,23 @@ void cbrCloudBodyPassthrough(void *src_ctx, HttpClientContext *cloud_ctx, const if (error == ERROR_END_OF_STREAM) { fsCloseFile(ctx->file); - char *tmpPath = custom_asprintf("%s.tmp", ctx->tonieInfo.contentPath); + char *tmpPath = custom_asprintf("%s.tmp", ctx->tonieInfo->contentPath); - fsDeleteFile(ctx->tonieInfo.contentPath); - fsRenameFile(tmpPath, ctx->tonieInfo.contentPath); - if (fsFileExists(ctx->tonieInfo.contentPath)) + fsDeleteFile(ctx->tonieInfo->contentPath); + fsRenameFile(tmpPath, ctx->tonieInfo->contentPath); + if (fsFileExists(ctx->tonieInfo->contentPath)) { - TRACE_INFO(">> Successfully cached %s\r\n", ctx->tonieInfo.contentPath); + TRACE_INFO(">> Successfully cached %s\r\n", ctx->tonieInfo->contentPath); } else { - TRACE_ERROR(">> Error caching %s\r\n", ctx->tonieInfo.contentPath); + TRACE_ERROR(">> Error caching %s\r\n", ctx->tonieInfo->contentPath); } free(tmpPath); } if (error != NO_ERROR) { - freeTonieInfo(&ctx->tonieInfo); + freeTonieInfo(ctx->tonieInfo); } } httpSend(ctx->connection, payload, length, HTTP_FLAG_DELAY); @@ -221,31 +220,33 @@ void setTonieboxSettings(TonieFreshnessCheckResponse *freshResp, settings_t *set freshResp->led = settings->toniebox.led; } -tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings) +tonie_info_t *getTonieInfoFromUid(uint64_t uid, settings_t *settings) { - tonie_info_t tonieInfo; - - tonieInfo.valid = false; - tonieInfo.updated = false; - tonieInfo.stream = false; - tonieInfo.tafHeader = NULL; - tonieInfo.contentPath = strdup(contentPath); - tonieInfo.exists = fsFileExists(contentPath); - - tonieInfo.contentConfig.live = false; - tonieInfo.contentConfig.nocloud = false; - tonieInfo.contentConfig.source = NULL; - tonieInfo.contentConfig.skip_seconds = 0; - tonieInfo.contentConfig.cache = false; - tonieInfo.contentConfig._updated = false; - tonieInfo.contentConfig._stream = false; - tonieInfo.contentConfig._streamFile = custom_asprintf("%s.stream", contentPath); - tonieInfo.contentConfig.cloud_ruid = NULL; - tonieInfo.contentConfig.cloud_auth = NULL; - tonieInfo.contentConfig.cloud_auth_len = 0; - tonieInfo.contentConfig.cloud_override = false; - tonieInfo.contentConfig.tonie_model = NULL; - tonieInfo.contentConfig._valid = false; + char *contentPath; + getContentPathFromUID(uid, &contentPath, settings); + tonie_info_t *tonieInfo = getTonieInfo(contentPath, settings); + osFreeMem(contentPath); + return tonieInfo; +} +tonie_info_t *getTonieInfoFromRuid(char ruid[17], settings_t *settings) +{ + char *contentPath; + getContentPathFromCharRUID(ruid, &contentPath, settings); + tonie_info_t *tonieInfo = getTonieInfo(contentPath, settings); + osFreeMem(contentPath); + return tonieInfo; +} +tonie_info_t *getTonieInfo(const char *contentPath, settings_t *settings) +{ + tonie_info_t *tonieInfo; + tonieInfo = osAllocMem(sizeof(tonie_info_t)); + + tonieInfo->valid = false; + tonieInfo->updated = false; + tonieInfo->stream = false; + tonieInfo->tafHeader = NULL; + tonieInfo->contentPath = strdup(contentPath); + tonieInfo->exists = fsFileExists(contentPath); if (osStrstr(contentPath, ".json") == NULL) { @@ -254,7 +255,7 @@ tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings) osStrlen(contentPath) - 18 == osStrlen(settings->internal.contentdirfull)) { // TODO: Nice checking if valid tonie path - load_content_json(contentPath, &tonieInfo.contentConfig); + load_content_json(contentPath, &tonieInfo->json); } FsFile *file = fsOpenFile(contentPath, FS_FILE_MODE_READ); @@ -271,14 +272,14 @@ tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings) fsReadFile(file, headerBuffer, protobufSize, &read_length); if (read_length == protobufSize) { - tonieInfo.tafHeader = toniebox_audio_file_header__unpack(NULL, protobufSize, (const uint8_t *)headerBuffer); - if (tonieInfo.tafHeader) + tonieInfo->tafHeader = toniebox_audio_file_header__unpack(NULL, protobufSize, (const uint8_t *)headerBuffer); + if (tonieInfo->tafHeader) { - tonieInfo.valid = true; - content_json_update_model(&tonieInfo.contentConfig, tonieInfo.tafHeader->audio_id); - if (tonieInfo.tafHeader->num_bytes == TONIE_LENGTH_MAX) + tonieInfo->valid = true; + content_json_update_model(&tonieInfo->json, tonieInfo->tafHeader->audio_id); + if (tonieInfo->tafHeader->num_bytes == TONIE_LENGTH_MAX) { - tonieInfo.stream = true; + tonieInfo->stream = true; } } } @@ -309,9 +310,9 @@ tonie_info_t getTonieInfo(const char *contentPath, settings_t *settings) void freeTonieInfo(tonie_info_t *tonieInfo) { - if (tonieInfo->contentConfig._updated) + if (tonieInfo->json._updated) { - save_content_json(tonieInfo->contentPath, &tonieInfo->contentConfig); + save_content_json(tonieInfo->contentPath, &tonieInfo->json); } if (tonieInfo->tafHeader) @@ -327,8 +328,9 @@ void freeTonieInfo(tonie_info_t *tonieInfo) if (tonieInfo->valid) { - free_content_json(&tonieInfo->contentConfig); + free_content_json(&tonieInfo->json); } + free(tonieInfo); } void httpPrepareHeader(HttpConnection *connection, const void *contentType, size_t contentLength) diff --git a/src/handler_api.c b/src/handler_api.c index 58a27b26..364371be 100644 --- a/src/handler_api.c +++ b/src/handler_api.c @@ -515,19 +515,19 @@ error_t handleApiFileIndex(HttpConnection *connection, const char_t *uri, const char desc[64]; desc[0] = 0; - tonie_info_t tafInfo = getTonieInfo(filePathAbsolute, client_ctx->settings); - if (tafInfo.valid) + tonie_info_t *tafInfo = getTonieInfo(filePathAbsolute, client_ctx->settings); + if (tafInfo->valid) { - osSnprintf(desc, sizeof(desc), "TAF:%08X:", tafInfo.tafHeader->audio_id); - for (int pos = 0; pos < tafInfo.tafHeader->sha1_hash.len; pos++) + osSnprintf(desc, sizeof(desc), "TAF:%08X:", tafInfo->tafHeader->audio_id); + for (int pos = 0; pos < tafInfo->tafHeader->sha1_hash.len; pos++) { char tmp[3]; - osSprintf(tmp, "%02X", tafInfo.tafHeader->sha1_hash.data[pos]); + osSprintf(tmp, "%02X", tafInfo->tafHeader->sha1_hash.data[pos]); osStrcat(desc, tmp); } } osFreeMem(filePathAbsolute); - freeTonieInfo(&tafInfo); + freeTonieInfo(tafInfo); cJSON *jsonEntry = cJSON_CreateObject(); cJSON_AddStringToObject(jsonEntry, "name", entry.name); @@ -1119,16 +1119,16 @@ error_t handleApiContent(HttpConnection *connection, const char_t *uri, const ch error = fsGetFileSize(file_path, &length); bool_t isStream = false; - tonie_info_t tafInfo = getTonieInfo(file_path, client_ctx->settings); + tonie_info_t *tafInfo = getTonieInfo(file_path, client_ctx->settings); - if (tafInfo.valid && tafInfo.stream) + if (tafInfo->valid && tafInfo->stream) { isStream = true; length = CONTENT_LENGTH_MAX; connection->response.noCache = true; } - freeTonieInfo(&tafInfo); + freeTonieInfo(tafInfo); if (error || length < startOffset) { diff --git a/src/handler_cloud.c b/src/handler_cloud.c index 20bb9bf4..aa9a44c0 100644 --- a/src/handler_cloud.c +++ b/src/handler_cloud.c @@ -159,15 +159,15 @@ bool checkCustomTonie(char *ruid, uint8_t *token, settings_t *settings) void markCustomTonie(tonie_info_t *tonieInfo) { - tonieInfo->contentConfig.nocloud = true; - tonieInfo->contentConfig._updated = true; + tonieInfo->json.nocloud = true; + tonieInfo->json._updated = true; TRACE_INFO("Marked custom tonie %s\r\n", tonieInfo->contentPath); } void markLiveTonie(tonie_info_t *tonieInfo) { - tonieInfo->contentConfig.live = true; - tonieInfo->contentConfig._updated = true; + tonieInfo->json.live = true; + tonieInfo->json._updated = true; TRACE_INFO("Marked custom tonie %s\r\n", tonieInfo->contentPath); } @@ -220,9 +220,8 @@ error_t handleCloudClaim(HttpConnection *connection, const char_t *uri, const ch time_format_current(current_time); mqtt_sendBoxEvent("LastCloudClaimTime", current_time, client_ctx); - tonie_info_t tonieInfo; - getContentPathFromCharRUID(ruid, &tonieInfo.contentPath, client_ctx->settings); - tonieInfo = getTonieInfo(tonieInfo.contentPath, client_ctx->settings); + tonie_info_t *tonieInfo; + tonieInfo = getTonieInfoFromRuid(ruid, client_ctx->settings); /* allow to override HTTP status code if needed */ bool served = false; @@ -231,24 +230,24 @@ error_t handleCloudClaim(HttpConnection *connection, const char_t *uri, const ch if (client_ctx->settings->cloud.dumpRuidAuthContentJson) { - dumpRuidAuth(&tonieInfo.contentConfig, ruid, token); + dumpRuidAuth(&tonieInfo->json, ruid, token); } - if (!tonieInfo.contentConfig.nocloud || tonieInfo.contentConfig.cloud_override) + if (!tonieInfo->json.nocloud || tonieInfo->json.cloud_override) { - if (checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo.contentConfig.cloud_override) + if (checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo->json.cloud_override) { TRACE_INFO(" >> custom tonie detected, nothing forwarded\r\n"); - markCustomTonie(&tonieInfo); + markCustomTonie(tonieInfo); } else if (client_ctx->settings->cloud.enabled && client_ctx->settings->cloud.enableV1Claim) { - if (tonieInfo.contentConfig.cloud_override) + if (tonieInfo->json.cloud_override) { - token = tonieInfo.contentConfig.cloud_auth; + token = tonieInfo->json.cloud_auth; convertTokenBytesToString(token, msg, client_ctx->settings->log.logFullAuth); - osMemcpy((char_t *)&uri[RUID_URI_CLAIM_BEGIN], tonieInfo.contentConfig.cloud_ruid, osStrlen(tonieInfo.contentConfig.cloud_ruid)); - TRACE_INFO("Serve cloud claim from alternative rUID %s, auth %s\r\n", tonieInfo.contentConfig.cloud_ruid, msg); + osMemcpy((char_t *)&uri[RUID_URI_CLAIM_BEGIN], tonieInfo->json.cloud_ruid, osStrlen(tonieInfo->json.cloud_ruid)); + TRACE_INFO("Serve cloud claim from alternative rUID %s, auth %s\r\n", tonieInfo->json.cloud_ruid, msg); } cbr_ctx_t ctx; req_cbr_t cbr = getCloudCbr(connection, uri, queryString, V1_CLAIM, &ctx, client_ctx); @@ -265,7 +264,7 @@ error_t handleCloudClaim(HttpConnection *connection, const char_t *uri, const ch TRACE_INFO(" >> nocloud content, nothing forwarded\r\n"); } - freeTonieInfo(&tonieInfo); + freeTonieInfo(tonieInfo); if (!served) { @@ -302,21 +301,20 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const convertTokenBytesToString(token, msg, client_ctx->settings->log.logFullAuth); TRACE_INFO(" >> client requested content for rUID %s, auth %s\r\n", ruid, msg); - tonie_info_t tonieInfo; - getContentPathFromCharRUID(ruid, &tonieInfo.contentPath, client_ctx->settings); - tonieInfo = getTonieInfo(tonieInfo.contentPath, client_ctx->settings); + tonie_info_t *tonieInfo; + tonieInfo = getTonieInfoFromRuid(ruid, client_ctx->settings); - if (!tonieInfo.contentConfig.nocloud && !noPassword && checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo.contentConfig.cloud_override) + if (!tonieInfo->json.nocloud && !noPassword && checkCustomTonie(ruid, token, client_ctx->settings) && !tonieInfo->json.cloud_override) { TRACE_INFO(" >> custom tonie detected, nothing forwarded\r\n"); - markCustomTonie(&tonieInfo); + markCustomTonie(tonieInfo); } settings_t *settings = client_ctx->settings; if (client_ctx->settings->cloud.dumpRuidAuthContentJson) { - dumpRuidAuth(&tonieInfo.contentConfig, ruid, token); + dumpRuidAuth(&tonieInfo->json, ruid, token); } bool setLive = false; @@ -324,7 +322,7 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const if (osStrlen(settings->internal.assign_unknown) > 0) { - if (!tonieInfo.exists) + if (!tonieInfo->exists) { assignFile = settings->internal.assign_unknown; TRACE_INFO(" >> this is a unknown tonie, assigning '%s'\r\n", assignFile); @@ -357,36 +355,36 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const break; } - tonie_info_t tonieInfoAssign = getTonieInfo(assignFile, client_ctx->settings); - if (!tonieInfoAssign.valid) + tonie_info_t *tonieInfoAssign = getTonieInfo(assignFile, client_ctx->settings); + if (!tonieInfoAssign->valid) { - freeTonieInfo(&tonieInfoAssign); + freeTonieInfo(tonieInfoAssign); TRACE_ERROR("TAF header invalid: %s\r\n", assignFile); break; } - char *dir = strdup(tonieInfo.contentPath); + char *dir = strdup(tonieInfo->contentPath); dir[osStrlen(dir) - 8] = '\0'; fsCreateDir(dir); osFreeMem(dir); - error = fsCopyFile(assignFile, tonieInfo.contentPath, true); + error = fsCopyFile(assignFile, tonieInfo->contentPath, true); if (error != NO_ERROR) { - freeTonieInfo(&tonieInfoAssign); - TRACE_ERROR("Could not copy %s to %s, error=%" PRIu32 "\r\n", assignFile, tonieInfo.contentPath, error); + freeTonieInfo(tonieInfoAssign); + TRACE_ERROR("Could not copy %s to %s, error=%" PRIu32 "\r\n", assignFile, tonieInfo->contentPath, error); break; } - char *oldFile = strdup(tonieInfo.contentPath); - freeTonieInfo(&tonieInfo); + char *oldFile = strdup(tonieInfo->contentPath); + freeTonieInfo(tonieInfo); tonieInfo = getTonieInfo(oldFile, client_ctx->settings); free(oldFile); - if (!tonieInfo.valid) + if (!tonieInfo->valid) { - TRACE_ERROR("TAF headerinvalid, delete it again: %s\r\n", tonieInfo.contentPath); - fsDeleteFile(tonieInfo.contentPath); + TRACE_ERROR("TAF headerinvalid, delete it again: %s\r\n", tonieInfo->contentPath); + fsDeleteFile(tonieInfo->contentPath); break; } @@ -394,7 +392,7 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const if (setLive) { - markLiveTonie(&tonieInfo); + markLiveTonie(tonieInfo); } } while (0); @@ -403,18 +401,18 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const error = NO_ERROR; } - if (tonieInfo.contentConfig._stream) + if (tonieInfo->json._stream) { - char *streamFileRel = &tonieInfo.contentConfig._streamFile[osStrlen(client_ctx->settings->internal.datadirfull)]; - TRACE_INFO("Serve streaming content from %s\r\n", tonieInfo.contentConfig.source); + char *streamFileRel = &tonieInfo->json._streamFile[osStrlen(client_ctx->settings->internal.datadirfull)]; + TRACE_INFO("Serve streaming content from %s\r\n", tonieInfo->json.source); connection->response.keepAlive = true; ffmpeg_stream_ctx_t ffmpeg_ctx; ffmpeg_ctx.active = false; ffmpeg_ctx.quit = false; - ffmpeg_ctx.source = tonieInfo.contentConfig.source; - ffmpeg_ctx.skip_seconds = tonieInfo.contentConfig.skip_seconds; - ffmpeg_ctx.targetFile = tonieInfo.contentConfig._streamFile; + ffmpeg_ctx.source = tonieInfo->json.source; + ffmpeg_ctx.skip_seconds = tonieInfo->json.skip_seconds; + ffmpeg_ctx.targetFile = tonieInfo->json._streamFile; ffmpeg_ctx.error = NO_ERROR; ffmpeg_ctx.taskId = osCreateTask(streamFileRel, &ffmpeg_stream_task, &ffmpeg_ctx, 10 * 1024, 0); @@ -424,10 +422,10 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const } if (ffmpeg_ctx.error == NO_ERROR) { - error_t error = httpSendResponseStream(connection, streamFileRel, tonieInfo.contentConfig._stream); + error_t error = httpSendResponseStream(connection, streamFileRel, tonieInfo->json._stream); if (error) { - TRACE_ERROR(" >> file %s not available or not send, error=%u...\r\n", tonieInfo.contentPath, error); + TRACE_ERROR(" >> file %s not available or not send, error=%u...\r\n", tonieInfo->contentPath, error); } } ffmpeg_ctx.active = false; @@ -436,27 +434,27 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const osDelayTask(100); } } - else if (tonieInfo.exists && tonieInfo.valid) + else if (tonieInfo->exists && tonieInfo->valid) { - TRACE_INFO("Serve local content from %s\r\n", tonieInfo.contentPath); + TRACE_INFO("Serve local content from %s\r\n", tonieInfo->contentPath); connection->response.keepAlive = true; - if (tonieInfo.stream) + if (tonieInfo->stream) { TRACE_INFO("Found streaming content\r\n"); } - error_t error = httpSendResponseStream(connection, &tonieInfo.contentPath[osStrlen(client_ctx->settings->internal.datadirfull)], tonieInfo.stream); + error_t error = httpSendResponseStream(connection, &tonieInfo->contentPath[osStrlen(client_ctx->settings->internal.datadirfull)], tonieInfo->stream); if (error) { - TRACE_ERROR(" >> file %s not available or not send, error=%u...\r\n", tonieInfo.contentPath, error); + TRACE_ERROR(" >> file %s not available or not send, error=%u...\r\n", tonieInfo->contentPath, error); } } else { - if (!client_ctx->settings->cloud.enabled || !client_ctx->settings->cloud.enableV2Content || tonieInfo.contentConfig.nocloud) + if (!client_ctx->settings->cloud.enabled || !client_ctx->settings->cloud.enableV2Content || tonieInfo->json.nocloud) { - if (tonieInfo.contentConfig.nocloud) + if (tonieInfo->json.nocloud) { TRACE_INFO("Content marked as no cloud and no content locally available\r\n"); } @@ -472,12 +470,12 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const { TRACE_INFO("Serve cloud content from %s\r\n", uri); - if (tonieInfo.contentConfig.cloud_override) + if (tonieInfo->json.cloud_override) { - token = tonieInfo.contentConfig.cloud_auth; + token = tonieInfo->json.cloud_auth; convertTokenBytesToString(token, msg, client_ctx->settings->log.logFullAuth); - osMemcpy((char_t *)&uri[RUID_URI_CONTENT_BEGIN], tonieInfo.contentConfig.cloud_ruid, osStrlen(tonieInfo.contentConfig.cloud_ruid)); - TRACE_INFO("Serve cloud from alternative rUID %s, auth %s\r\n", tonieInfo.contentConfig.cloud_ruid, msg); + osMemcpy((char_t *)&uri[RUID_URI_CONTENT_BEGIN], tonieInfo->json.cloud_ruid, osStrlen(tonieInfo->json.cloud_ruid)); + TRACE_INFO("Serve cloud from alternative rUID %s, auth %s\r\n", tonieInfo->json.cloud_ruid, msg); } connection->response.keepAlive = true; @@ -487,7 +485,7 @@ error_t handleCloudContent(HttpConnection *connection, const char_t *uri, const error = NO_ERROR; } } - freeTonieInfo(&tonieInfo); + freeTonieInfo(tonieInfo); return error; } @@ -582,9 +580,8 @@ error_t handleCloudFreshnessCheck(HttpConnection *connection, const char_t *uri, for (uint16_t i = 0; i < freshReq->n_tonie_infos; i++) { - tonie_info_t tonieInfo; - getContentPathFromUID(freshReq->tonie_infos[i]->uid, &tonieInfo.contentPath, client_ctx->settings); - tonieInfo = getTonieInfo(tonieInfo.contentPath, client_ctx->settings); + tonie_info_t *tonieInfo; + tonieInfo = getTonieInfoFromUid(freshReq->tonie_infos[i]->uid, client_ctx->settings); char date_buffer_box[32]; bool_t custom_box; @@ -597,26 +594,26 @@ error_t handleCloudFreshnessCheck(HttpConnection *connection, const char_t *uri, if (custom_box) boxAudioId += TEDDY_BENCH_AUDIO_ID_DEDUCT; - if (tonieInfo.valid) + if (tonieInfo->valid) { - uint32_t serverAudioId = tonieInfo.tafHeader->audio_id; + uint32_t serverAudioId = tonieInfo->tafHeader->audio_id; checkAudioIdForCustom(&custom_server, date_buffer_server, serverAudioId); if (custom_server) serverAudioId += TEDDY_BENCH_AUDIO_ID_DEDUCT; - tonieInfo.updated = boxAudioId < serverAudioId; - tonieInfo.updated = tonieInfo.updated || (client_ctx->settings->cloud.updateOnLowerAudioId && (boxAudioId > serverAudioId)); + tonieInfo->updated = boxAudioId < serverAudioId; + tonieInfo->updated = tonieInfo->updated || (client_ctx->settings->cloud.updateOnLowerAudioId && (boxAudioId > serverAudioId)); if (client_ctx->settings->cloud.prioCustomContent) { if (custom_box && !custom_server) - tonieInfo.updated = false; + tonieInfo->updated = false; if (!custom_box && custom_server) - tonieInfo.updated = true; + tonieInfo->updated = true; } } - if (!tonieInfo.contentConfig.nocloud) + if (!tonieInfo->json.nocloud) { freshReqCloud.tonie_infos[freshReqCloud.n_tonie_infos++] = freshReq->tonie_infos[i]; } @@ -634,32 +631,32 @@ error_t handleCloudFreshnessCheck(HttpConnection *connection, const char_t *uri, (void)custom_server; TRACE_INFO(" uid: %016" PRIX64 ", nocloud: %d, live: %d, updated: %d, audioid: %08X (%s%s)", freshReq->tonie_infos[i]->uid, - tonieInfo.contentConfig.nocloud, - tonieInfo.contentConfig.live || isFlex || tonieInfo.stream, - tonieInfo.updated, + tonieInfo->json.nocloud, + tonieInfo->json.live || isFlex || tonieInfo->stream, + tonieInfo->updated, freshReq->tonie_infos[i]->audio_id, date_buffer_box, custom_box ? ", custom" : ""); - if (tonieInfo.valid) + if (tonieInfo->valid) { TRACE_INFO_RESUME(", audioid-server: %08X (%s%s)", - tonieInfo.tafHeader->audio_id, + tonieInfo->tafHeader->audio_id, date_buffer_server, custom_server ? ", custom" : ""); } else { - content_json_update_model(&tonieInfo.contentConfig, freshReq->tonie_infos[i]->audio_id); + content_json_update_model(&tonieInfo->json, freshReq->tonie_infos[i]->audio_id); } TRACE_INFO_RESUME("\r\n"); - if (tonieInfo.contentConfig.live || tonieInfo.updated || tonieInfo.stream || isFlex) + if (tonieInfo->json.live || tonieInfo->updated || tonieInfo->stream || isFlex) { freshResp.tonie_marked[freshResp.n_tonie_marked++] = freshReq->tonie_infos[i]->uid; } - freeTonieInfo(&tonieInfo); + freeTonieInfo(tonieInfo); } if (client_ctx->settings->cloud.enabled && client_ctx->settings->cloud.enableV1FreshnessCheck) From ed8c3a849cd66b1e065f8b24cbae5397d38d3e52 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 11:22:17 +0000 Subject: [PATCH 6/8] init contentJson when no json exists (crashfix) --- src/handler.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/handler.c b/src/handler.c index fc82b986..f2017911 100644 --- a/src/handler.c +++ b/src/handler.c @@ -247,6 +247,7 @@ tonie_info_t *getTonieInfo(const char *contentPath, settings_t *settings) tonieInfo->tafHeader = NULL; tonieInfo->contentPath = strdup(contentPath); tonieInfo->exists = fsFileExists(contentPath); + osMemset(&tonieInfo->json, 0, sizeof(contentJson_t)); if (osStrstr(contentPath, ".json") == NULL) { From e195fe00eb3f29ed5957b230390b5d3e1118e8e3 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 19:33:59 +0000 Subject: [PATCH 7/8] also search for custom audio ids. move TEDDY_BENCH_AUDIO_ID_DEDUCT --- include/toniesJson.h | 2 ++ src/handler_cloud.c | 2 +- src/toniesJson.c | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/toniesJson.h b/include/toniesJson.h index 70b1c32e..9a3ec156 100644 --- a/include/toniesJson.h +++ b/include/toniesJson.h @@ -3,6 +3,8 @@ #include #include +#define TEDDY_BENCH_AUDIO_ID_DEDUCT 0x50000000 + typedef struct { uint16_t no; diff --git a/src/handler_cloud.c b/src/handler_cloud.c index aa9a44c0..398e1717 100644 --- a/src/handler_cloud.c +++ b/src/handler_cloud.c @@ -14,6 +14,7 @@ #include "server_helpers.h" #include "toniefile.h" +#include "toniesJson.h" void convertTokenBytesToString(uint8_t *token, char *msg, bool_t logFullAuth) { @@ -507,7 +508,6 @@ error_t handleCloudContentV2(HttpConnection *connection, const char_t *uri, cons return NO_ERROR; } -#define TEDDY_BENCH_AUDIO_ID_DEDUCT 0x50000000 void checkAudioIdForCustom(bool_t *isCustom, char date_buffer[32], time_t audioId); void checkAudioIdForCustom(bool_t *isCustom, char date_buffer[32], time_t audioId) { diff --git a/src/toniesJson.c b/src/toniesJson.c index 6b1c1ddc..31c27353 100644 --- a/src/toniesJson.c +++ b/src/toniesJson.c @@ -139,7 +139,8 @@ toniesJson_item_t *tonies_byAudioId_base(uint32_t audio_id, toniesJson_item_t *t { for (size_t j = 0; j < toniesCache[i].audio_ids_count; j++) { - if (toniesCache[i].audio_ids[j] == audio_id) + + if (toniesCache[i].audio_ids[j] == audio_id || (audio_id < TEDDY_BENCH_AUDIO_ID_DEDUCT && toniesCache[i].audio_ids[j] == audio_id + TEDDY_BENCH_AUDIO_ID_DEDUCT)) return &toniesCache[i]; } } From 451dfe2ca6d78ba2ca45906a8dd7becba719a1a0 Mon Sep 17 00:00:00 2001 From: SciLor Date: Wed, 4 Oct 2023 19:42:24 +0000 Subject: [PATCH 8/8] add toniebox state use model for rtnl audio id workaround --- include/net_config.h | 4 ++-- include/toniebox_state.h | 27 +++++++++++++++++++++++++++ include/toniesJson.h | 2 ++ src/handler_rtnl.c | 23 ++++++++++++++++++++++- src/main.c | 2 ++ src/mqtt.c | 6 +++--- src/server.c | 6 ++++-- src/toniebox_state.c | 21 +++++++++++++++++++++ src/toniesJson.c | 33 +++++++++++++++++++++++++++++++++ 9 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 include/toniebox_state.h create mode 100644 src/toniebox_state.c diff --git a/include/net_config.h b/include/net_config.h index 7abc919f..c9c61ff5 100644 --- a/include/net_config.h +++ b/include/net_config.h @@ -32,13 +32,13 @@ #define _NET_CONFIG_H #include "settings.h" +#include "toniebox_state.h" #define AUTH_TOKEN_LENGTH 32 typedef struct { settings_t *settings; - const char *box_id; - const char *box_name; + toniebox_state_t *state; } client_ctx_t; typedef struct diff --git a/include/toniebox_state.h b/include/toniebox_state.h new file mode 100644 index 00000000..889ec26e --- /dev/null +++ b/include/toniebox_state.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +typedef struct +{ + const char *id; + const char *name; +} toniebox_state_box_t; + +typedef struct +{ + uint64_t uid; + bool valid; + uint32_t audio_id; +} toniebox_state_tag_t; + +typedef struct +{ + toniebox_state_box_t box; + toniebox_state_tag_t tag; +} toniebox_state_t; + +void toniebox_state_init(); +toniebox_state_t *get_toniebox_state(); +toniebox_state_t *get_toniebox_state_id(uint8_t id); \ No newline at end of file diff --git a/include/toniesJson.h b/include/toniesJson.h index 9a3ec156..3b5a7422 100644 --- a/include/toniesJson.h +++ b/include/toniesJson.h @@ -25,4 +25,6 @@ typedef struct void tonies_init(); void tonies_readJson(char *source, toniesJson_item_t **toniesCache, size_t *toniesCount); toniesJson_item_t *tonies_byAudioId(uint32_t audio_id); +toniesJson_item_t *tonies_byModel(char *model); +toniesJson_item_t *tonies_byAudioIdModel(uint32_t audio_id, char *model); void tonies_deinit(); \ No newline at end of file diff --git a/src/handler_rtnl.c b/src/handler_rtnl.c index 8e3c1764..94ba9b83 100644 --- a/src/handler_rtnl.c +++ b/src/handler_rtnl.c @@ -282,6 +282,10 @@ void rtnlEvent(HttpConnection *connection, TonieRtnlRPC *rpc, client_ctx_t *clie mqtt_sendBoxEvent("TagInvalid", "", client_ctx); break; case RTNL3_TYPE_PLAYBACK_STOPPED: + client_ctx->state->tag.audio_id = 0; + client_ctx->state->tag.valid = false; + client_ctx->state->tag.uid = 0; + sse_sendEvent("playback", "stopped", true); mqtt_sendBoxEvent("Playback", "OFF", client_ctx); mqtt_sendBoxEvent("TagValid", "", client_ctx); @@ -309,8 +313,11 @@ void rtnlEvent(HttpConnection *connection, TonieRtnlRPC *rpc, client_ctx_t *clie for (size_t i = 0; i < rpc->log2->field6.len; i++) { osSprintf(&buffer[i * 2], "%02X", rpc->log2->field6.data[(i + 4) % 8]); + client_ctx->state->tag.uid += (rpc->log2->field6.data[i] << i); } } + client_ctx->state->tag.uid = strtoull(buffer, NULL, 16); + client_ctx->state->tag.valid = false; sse_sendEvent("TagInvalid", buffer, true); mqtt_sendBoxEvent("TagInvalid", buffer, client_ctx); mqtt_sendBoxEvent("TagValid", "", client_ctx); @@ -324,6 +331,8 @@ void rtnlEvent(HttpConnection *connection, TonieRtnlRPC *rpc, client_ctx_t *clie osSprintf(&buffer[i * 2], "%02X", rpc->log2->field6.data[(i + 4) % 8]); } } + client_ctx->state->tag.uid = strtoull(buffer, NULL, 16); + client_ctx->state->tag.valid = true; sse_sendEvent("TagValid", buffer, true); mqtt_sendBoxEvent("TagValid", buffer, client_ctx); mqtt_sendBoxEvent("TagInvalid", "", client_ctx); @@ -331,15 +340,27 @@ void rtnlEvent(HttpConnection *connection, TonieRtnlRPC *rpc, client_ctx_t *clie else if ((rpc->log2->function_group == RTNL2_FUGR_AUDIO_A && (rpc->log2->function == RTNL2_FUNC_AUDIO_ID_CC3200 || rpc->log2->function == RTNL2_FUNC_AUDIO_ID_ESP32)) || (rpc->log2->function_group == RTNL2_FUGR_AUDIO_B && rpc->log2->function == RTNL2_FUNC_AUDIO_ID)) { uint32_t audioId = read_little_endian(rpc->log2->field6.data); + client_ctx->state->tag.audio_id = audioId; osSprintf(buffer, "%d", audioId); toniesJson_item_t *item = tonies_byAudioId(audioId); sse_sendEvent("ContentAudioId", buffer, true); mqtt_sendBoxEvent("ContentAudioId", buffer, client_ctx); + + if (item == NULL) + { + tonie_info_t *tonieInfo = getTonieInfoFromUid(client_ctx->state->tag.uid, client_ctx->settings); + if (tonieInfo->valid) + { + item = tonies_byModel(tonieInfo->json.tonie_model); + } + freeTonieInfo(tonieInfo); + } + if (item == NULL) { sse_sendEvent("ContentTitle", "Unknown", true); mqtt_sendBoxEvent("ContentTitle", "Unknown", client_ctx); - if (audioId < 0x50000000) + if (audioId < TEDDY_BENCH_AUDIO_ID_DEDUCT) { /* custom tonie */ char *url = custom_asprintf("%s/img_custom.png", settings_get_string("core.host_url")); diff --git a/src/main.c b/src/main.c index d5be1015..8586a545 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,7 @@ #include "cloud_request.h" #include "settings.h" +#include "toniebox_state.h" #include "mqtt.h" #include "cert.h" #include "toniefile.h" @@ -131,6 +132,7 @@ int_t main(int argc, char *argv[]) TRACE_ERROR("Make sure the config path exists and is writable\r\n"); return -1; } + toniebox_state_init(); platform_init(); cJSON_Hooks hooks = {.malloc_fn = osAllocMem, .free_fn = osFreeMem}; diff --git a/src/mqtt.c b/src/mqtt.c index 5b109767..4d9baaeb 100644 --- a/src/mqtt.c +++ b/src/mqtt.c @@ -667,8 +667,8 @@ void mqtt_settings_rx(t_ha_info *ha_info, const t_ha_entity *entity, void *ctx, error_t mqtt_init_box(t_ha_info *ha_box_instance, client_ctx_t *client_ctx) { t_ha_entity entity; - const char *box_id = client_ctx->box_id; - const char *box_name = client_ctx->box_name; + const char *box_id = client_ctx->state->box.id; + const char *box_name = client_ctx->state->box.name; if (!box_id) { @@ -888,7 +888,7 @@ t_ha_info *mqtt_get_box(client_ctx_t *client_ctx) { t_ha_info *ret = NULL; - const char *box_id = client_ctx->box_id; + const char *box_id = client_ctx->state->box.id; char *name = custom_asprintf("%s_Box_%s", settings_get_string("mqtt.topic"), box_id); diff --git a/src/server.c b/src/server.c index 3549abb9..ce9619c4 100644 --- a/src/server.c +++ b/src/server.c @@ -128,6 +128,7 @@ error_t httpServerRequestCallback(HttpConnection *connection, const char_t *uri) client_ctx_t *client_ctx = &connection->private.client_ctx; osMemset(client_ctx, 0x00, sizeof(client_ctx_t)); client_ctx->settings = get_settings(); + client_ctx->state = get_toniebox_state(); if (connection->tlsContext) { @@ -148,6 +149,7 @@ error_t httpServerRequestCallback(HttpConnection *connection, const char_t *uri) { client_ctx->settings = get_settings_cn(subject); } + client_ctx->state = get_toniebox_state_id(client_ctx->settings->internal.overlayNumber); char *ua = connection->request.userAgent; if (ua != NULL && osStrlen(ua) > 3) @@ -258,8 +260,8 @@ error_t httpServerRequestCallback(HttpConnection *connection, const char_t *uri) } } } - client_ctx->box_id = client_ctx->settings->commonName; - client_ctx->box_name = client_ctx->settings->boxName; + client_ctx->state->box.id = client_ctx->settings->commonName; + client_ctx->state->box.name = client_ctx->settings->boxName; mutex_unlock(MUTEX_CLIENT_CTX); connection->response.keepAlive = connection->request.keepAlive; diff --git a/src/toniebox_state.c b/src/toniebox_state.c new file mode 100644 index 00000000..56ce3899 --- /dev/null +++ b/src/toniebox_state.c @@ -0,0 +1,21 @@ +#include "toniebox_state.h" +#include "settings.h" + +static toniebox_state_t Box_State_Overlay[MAX_OVERLAYS]; + +void toniebox_state_init() +{ + for (size_t i = 0; i < MAX_OVERLAYS; i++) + { + osMemset(&Box_State_Overlay[i], 0, sizeof(toniebox_state_t)); + } +} + +toniebox_state_t *get_toniebox_state() +{ + return get_toniebox_state_id(0); +} +toniebox_state_t *get_toniebox_state_id(uint8_t id) +{ + return &Box_State_Overlay[id]; +} \ No newline at end of file diff --git a/src/toniesJson.c b/src/toniesJson.c index 31c27353..128fe43a 100644 --- a/src/toniesJson.c +++ b/src/toniesJson.c @@ -158,6 +158,39 @@ toniesJson_item_t *tonies_byAudioId(uint32_t audio_id) } return tonies_byAudioId_base(audio_id, toniesJsonCache, toniesJsonCount); } +toniesJson_item_t *tonies_byModel_base(char *model, toniesJson_item_t *toniesCache, size_t toniesCount) +{ + if (model == NULL || osStrcmp(model, "") == 0) + return NULL; +#if TONIES_JSON_CACHED == 1 + for (size_t i = 0; i < toniesCount; i++) + { + if (osStrcmp(toniesCache[i].model, model) == 0) + return &toniesCache[i]; + } +#else + // cJSON_ParseWithLengthOpts +#endif + return NULL; +} +toniesJson_item_t *tonies_byModel(char *model) +{ + toniesJson_item_t *item = tonies_byModel_base(model, toniesCustomJsonCache, toniesCustomJsonCount); + if (item) + { + return item; + } + return tonies_byModel_base(model, toniesJsonCache, toniesJsonCount); +} +toniesJson_item_t *tonies_byAudioIdModel(uint32_t audio_id, char *model) +{ + toniesJson_item_t *item = tonies_byAudioId(audio_id); + if (item) + { + return item; + } + return tonies_byModel(model); +} void tonies_deinit_base(toniesJson_item_t *toniesCache, size_t *toniesCount) { #if TONIES_JSON_CACHED == 1