From 3419ff3a8516104fcd96be2667ab337c0c71a254 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Thu, 11 Jun 2026 10:16:14 +0300 Subject: [PATCH] debug: single source of truth for category names, GUI dynamic labels - debug_get_category_name(): replace switch/case with table lookup in g_debug_categories[] - etcpmon_gui: remove hardcoded cat_names[], create labels/radios dynamically from server CSV --- lib/debug_config.c | 29 ++--------------- tools/etcpmon/etcpmon_gui.c | 64 ++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/lib/debug_config.c b/lib/debug_config.c index 5e954f8e..f8b5e24e 100644 --- a/lib/debug_config.c +++ b/lib/debug_config.c @@ -199,32 +199,9 @@ void debug_apply_global_level(const char* level_name) { /* Get category name for logging */ const char* debug_get_category_name(debug_category_t category_idx) { - switch (category_idx) { - case DEBUG_CATEGORY_UASYNC: return "UASYNC"; - case DEBUG_CATEGORY_LL_QUEUE: return "LL_QUEUE"; - case DEBUG_CATEGORY_CONNECTION: return "CONNECTION"; - case DEBUG_CATEGORY_ETCP: return "ETCP"; - case DEBUG_CATEGORY_CRYPTO: return "CRYPTO"; - case DEBUG_CATEGORY_MEMORY: return "MEMORY"; - case DEBUG_CATEGORY_TIMING: return "TIMING"; - case DEBUG_CATEGORY_CONFIG: return "CONFIG"; - case DEBUG_CATEGORY_TUN: return "TUN"; - case DEBUG_CATEGORY_ROUTING: return "ROUTING"; - case DEBUG_CATEGORY_TIMERS: return "TIMERS"; - case DEBUG_CATEGORY_NORMALIZER: return "NORMALIZER"; - case DEBUG_CATEGORY_BGP: return "BGP"; - case DEBUG_CATEGORY_SOCKET: return "SOCKET"; - case DEBUG_CATEGORY_CONTROL: return "CONTROL"; - case DEBUG_CATEGORY_DUMP: return "DUMP"; - case DEBUG_CATEGORY_TRAFFIC: return "TRAFFIC"; - case DEBUG_CATEGORY_DEBUG: return "DEBUG"; - case DEBUG_CATEGORY_GENERAL: return "GENERAL"; - case DEBUG_CATEGORY_NAT: return "NAT"; - case DEBUG_CATEGORY_KEEPALIVE: return "KEEPALIVE"; - case DEBUG_CATEGORY_ETCPROUTE: return "ETCPROUTE"; - case DEBUG_CATEGORY_NONE: return "NONE"; - default: return "UNKNOWN"; - } + for (int i = 0; g_debug_categories[i].name; i++) + if (g_debug_categories[i].category == category_idx) return g_debug_categories[i].name; + return "UNKNOWN"; } /* Global debug configuration */ diff --git a/tools/etcpmon/etcpmon_gui.c b/tools/etcpmon/etcpmon_gui.c index 5b556db8..a1dc992f 100644 --- a/tools/etcpmon/etcpmon_gui.c +++ b/tools/etcpmon/etcpmon_gui.c @@ -746,14 +746,7 @@ static void CreateControls(struct etcpmon_app* app) { "N\r\nO\r\nN\r\nE", "E\r\nR\r\nR\r\nO\r\nR", "W\r\nA\r\nR\r\nN", "I\r\nN\r\nF\r\nO", "D\r\nE\r\nB\r\nU\r\nG", "T\r\nR\r\nA\r\nC\r\nE" }; - static const char* cat_names[] = { - "UASYNC","LL_QUEUE","CONNECTION","ETCP","CRYPTO", - "MEMORY","TIMING","CONFIG","TUN","ROUTING", - "TIMERS","NORMALIZER","BGP","SOCKET","CONTROL", - "DUMP","TRAFFIC","DEBUG_CAT","GENERAL","NAT","KEEPALIVE","ETCPROUTE","BBR" - }; - int ncat = sizeof(cat_names) / sizeof(cat_names[0]); - app->debug_cat_count = ncat; + app->debug_cat_count = 0; CreateWindowExA(0, "STATIC", "Global:", WS_CHILD | WS_VISIBLE, 1015, dy + 2, 55, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL); @@ -772,21 +765,6 @@ static void CreateControls(struct etcpmon_app* app) { WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER | ES_MULTILINE, lx, dy, 22, 60, hWnd, (HMENU)(UINT_PTR)(IDC_DEBUG_HEADER_BASE + l), hInst, NULL); } - - dy += 65; - for (int r = 0; r < ncat; r++) { - app->hDebugCatLabel[r] = CreateWindowExA(0, "STATIC", cat_names[r], - WS_CHILD | WS_VISIBLE | SS_LEFT | SS_CENTERIMAGE, - 1015, dy + 1, 80, 16, hWnd, (HMENU)(UINT_PTR)(IDC_DEBUG_NAME_BASE + r), hInst, NULL); - for (int l = 0; l < 6; l++) { - int lx = 1100 + l * 22; - DWORD style = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON; - if (l == 0) style |= WS_GROUP; - app->hDebugCatRadio[r][l] = CreateWindowExA(0, "BUTTON", "", - style, lx, dy, 20, 16, hWnd, (HMENU)(UINT_PTR)(IDC_DEBUG_ROW_BASE + r * 8 + l), hInst, NULL); - } - dy += 18; - } } } @@ -1150,10 +1128,50 @@ static void OnDebugRadio(struct etcpmon_app* app, int control_id) { in_handler = 0; } +static void RecreateDebugCats(struct etcpmon_app* app) { + if (!app || !app->client || !app->hWndMain) return; + struct etcpmon_client* cl = app->client; + if (cl->debug_category_count == 0) return; + + HINSTANCE hInst = app->hInstance; + HWND hWnd = app->hWndMain; + int ncat = cl->debug_category_count; + if (ncat > IDC_DEBUG_MAX_CAT) ncat = IDC_DEBUG_MAX_CAT; + app->debug_cat_count = ncat; + + int dy = 485 + 20 + 22 + 65; // GroupBox top + global row + header row + header height + const char* names = cl->debug_category_names; + const char* p = names; + for (int r = 0; r < ncat; r++) { + const char* end = strchr(p, ','); + size_t len = end ? (size_t)(end - p) : strlen(p); + char buf[64]; + size_t copy = len < sizeof(buf) - 1 ? len : sizeof(buf) - 1; + memcpy(buf, p, copy); buf[copy] = '\0'; + + app->hDebugCatLabel[r] = CreateWindowExA(0, "STATIC", buf, + WS_CHILD | WS_VISIBLE | SS_LEFT | SS_CENTERIMAGE, + 1015, dy + 1, 80, 16, hWnd, (HMENU)(UINT_PTR)(IDC_DEBUG_NAME_BASE + r), hInst, NULL); + for (int l = 0; l < 6; l++) { + int lx = 1100 + l * 22; + DWORD style = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON; + if (l == 0) style |= WS_GROUP; + app->hDebugCatRadio[r][l] = CreateWindowExA(0, "BUTTON", "", + style, lx, dy, 20, 16, hWnd, (HMENU)(UINT_PTR)(IDC_DEBUG_ROW_BASE + r * 8 + l), hInst, NULL); + } + dy += 18; + + p = end ? end + 1 : p + len; + } +} + static void RefreshDebugUI(struct etcpmon_app* app) { if (!app || !app->client) return; struct etcpmon_client* cl = app->client; + if (app->debug_cat_count == 0 && cl->debug_category_count > 0) + RecreateDebugCats(app); + for (int l = 0; l <= 5; l++) { if (app->hDebugGlobalRadio[l]) SendMessage(app->hDebugGlobalRadio[l], BM_SETCHECK,