Browse Source

graph bugfix

nodeinfo-routing-update
jeka 1 month ago
parent
commit
9113428e7d
  1. 2
      tools/etcpmon/build.sh
  2. 64
      tools/etcpmon/etcpmon_client.c
  3. 37
      tools/etcpmon/etcpmon_client.h
  4. 105
      tools/etcpmon/etcpmon_gui.c
  5. 47
      tools/etcpmon/etcpmon_gui.h

2
tools/etcpmon/build.sh

@ -29,7 +29,7 @@ LDFLAGS="-mwindows"
LIBS="-lws2_32 -lcomctl32 -luser32 -lgdi32"
TARGET="etcpmon.exe"
SRCS="etcpmon_main.c etcpmon_gui.c etcpmon_client.c"
SRCS="etcpmon_main.c etcpmon_gui.c etcpmon_client.c etcpmon_graph.c"
OBJ_FILES=""
log "Compiler: $CC"

64
tools/etcpmon/etcpmon_client.c

@ -14,7 +14,7 @@
#define LOG_FILENAME "etcpmon.log"
/* Get current timestamp in milliseconds (Unix epoch) */
static uint64_t get_timestamp_ms(void) {
uint64_t get_timestamp_ms(void) {
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
@ -46,6 +46,7 @@ void etcpmon_client_init(struct etcpmon_client* client) {
client->connected = 0;
client->fully_connected = 0;
client->log_file = NULL;
memset(&client->history, 0, sizeof(client->history));
}
void etcpmon_client_cleanup(struct etcpmon_client* client) {
@ -367,6 +368,8 @@ static void handle_response(struct etcpmon_client* client, uint8_t msg_type,
client->on_metrics(client->last_metrics, client->last_links,
links_count, client->user_data);
}
etcpmon_client_add_to_history(client, client->last_metrics);
}
break;
}
@ -579,3 +582,62 @@ const char* etcpmon_client_get_conn_name(struct etcpmon_client* client, uint64_t
}
return NULL;
}
struct metrics_history* etcpmon_client_get_history(struct etcpmon_client* client) {
if (!client) return NULL;
return &client->history;
}
void etcpmon_client_add_to_history(struct etcpmon_client* client, struct etcpmon_rsp_metrics* metrics) {
if (!client || !metrics) return;
struct metrics_history* h = &client->history;
int idx = h->head;
if (client->log_file) {
fprintf(client->log_file, "add_to_history: rtt_last=%u rtt_avg10=%u rtt_avg100=%u jitter=%u\n",
metrics->etcp.rtt_last, metrics->etcp.rtt_avg_10, metrics->etcp.rtt_avg_100, metrics->etcp.jitter);
fflush(client->log_file);
}
float scale = 0.1f; // to ms (protocol: 0.1ms units)
h->values[GRAPH_METRIC_RTT_LAST][idx] = (float)metrics->etcp.rtt_last * scale;
h->values[GRAPH_METRIC_RTT_AVG10][idx] = (float)metrics->etcp.rtt_avg_10 * scale;
h->values[GRAPH_METRIC_RTT_AVG100][idx] = (float)metrics->etcp.rtt_avg_100 * scale;
h->values[GRAPH_METRIC_JITTER][idx] = (float)metrics->etcp.jitter * scale;
uint32_t retrans_delta = 0;
uint32_t acks_delta = 0;
uint64_t bytes_delta = 0;
if (h->count > 0) {
if (metrics->etcp.retrans_count >= h->last_retrans) {
retrans_delta = metrics->etcp.retrans_count - h->last_retrans;
}
if (metrics->etcp.ack_count >= h->last_acks) {
acks_delta = metrics->etcp.ack_count - h->last_acks;
}
if (metrics->etcp.bytes_sent_total >= h->last_bytes_sent) {
bytes_delta = metrics->etcp.bytes_sent_total - h->last_bytes_sent;
}
}
h->last_retrans = metrics->etcp.retrans_count;
h->last_acks = metrics->etcp.ack_count;
h->last_bytes_sent = metrics->etcp.bytes_sent_total;
h->values[GRAPH_METRIC_RETRANS][idx] = (float)retrans_delta;
h->values[GRAPH_METRIC_ACKS][idx] = (float)acks_delta;
h->values[GRAPH_METRIC_INFLIGHT][idx] = (float)metrics->etcp.unacked_bytes;
h->values[GRAPH_METRIC_BYTES_SENT][idx] = (float)bytes_delta;
h->head = (h->head + 1) % GRAPH_HISTORY_SIZE;
if (h->count < GRAPH_HISTORY_SIZE) {
h->count++;
}
if (client->log_file) {
fprintf(client->log_file, "history updated: count=%d head=%d\n", h->count, h->head);
fflush(client->log_file);
}
}

37
tools/etcpmon/etcpmon_client.h

@ -16,6 +16,32 @@
extern "C" {
#endif
/* Graph history size (samples) */
#define GRAPH_HISTORY_SIZE 860
/* Graph metrics types */
typedef enum {
GRAPH_METRIC_RTT_LAST = 0,
GRAPH_METRIC_RTT_AVG10,
GRAPH_METRIC_RTT_AVG100,
GRAPH_METRIC_JITTER,
GRAPH_METRIC_RETRANS,
GRAPH_METRIC_ACKS,
GRAPH_METRIC_INFLIGHT,
GRAPH_METRIC_BYTES_SENT,
GRAPH_METRIC_COUNT
} graph_metric_type_t;
/* Metrics history buffer */
struct metrics_history {
float values[GRAPH_METRIC_COUNT][GRAPH_HISTORY_SIZE];
int head;
int count;
uint32_t last_retrans;
uint32_t last_acks;
uint64_t last_bytes_sent;
};
/* Client state */
struct etcpmon_client {
SOCKET sock;
@ -44,6 +70,9 @@ struct etcpmon_client {
/* Log file */
FILE* log_file;
/* Metrics history for graph */
struct metrics_history history;
/* Callbacks */
void (*on_connected)(void* user_data);
void (*on_disconnected)(void* user_data);
@ -108,6 +137,14 @@ void etcpmon_client_set_callbacks(struct etcpmon_client* client,
/* Get connection name by peer_id */
const char* etcpmon_client_get_conn_name(struct etcpmon_client* client, uint64_t peer_id);
/* Get metrics history */
struct metrics_history* etcpmon_client_get_history(struct etcpmon_client* client);
/* Add metrics to history */
void etcpmon_client_add_to_history(struct etcpmon_client* client, struct etcpmon_rsp_metrics* metrics);
uint64_t get_timestamp_ms(void); // Add this declaration
#ifdef __cplusplus
}
#endif

105
tools/etcpmon/etcpmon_gui.c

@ -16,6 +16,7 @@
#include "etcpmon_client.h"
#include "etcpmon_protocol.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#pragma comment(lib, "comctl32.lib")
@ -23,7 +24,7 @@
//#pragma comment(lib, "gdi32.lib")
#define WINDOW_WIDTH 900
#define WINDOW_HEIGHT 700
#define WINDOW_HEIGHT 900
#define UPDATE_INTERVAL 100 /* 100ms */
/* Global app pointer for callbacks */
@ -87,6 +88,21 @@ int etcpmon_gui_init(struct etcpmon_app* app, HINSTANCE hInstance) {
return -1;
}
/* Register Graph window class */
WNDCLASSEXA wcexGraph;
memset(&wcexGraph, 0, sizeof(wcexGraph));
wcexGraph.cbSize = sizeof(wcexGraph);
wcexGraph.style = CS_HREDRAW | CS_VREDRAW;
wcexGraph.lpfnWndProc = GraphWndProc;
wcexGraph.hInstance = hInstance;
wcexGraph.hIcon = NULL;
wcexGraph.hCursor = LoadCursor(NULL, IDC_CROSS);
wcexGraph.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcexGraph.lpszClassName = "ETCPMonGraph";
wcexGraph.hIconSm = NULL;
RegisterClassExA(&wcexGraph);
/* Initialize Winsock */
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
@ -104,7 +120,7 @@ HWND etcpmon_gui_create_window(struct etcpmon_app* app) {
0,
ETCPMON_WINDOW_CLASS,
"ETCP Monitor",
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME,
CW_USEDEFAULT, CW_USEDEFAULT,
WINDOW_WIDTH, WINDOW_HEIGHT,
NULL, NULL, app->hInstance, app
@ -192,8 +208,55 @@ static void CreateControls(struct etcpmon_app* app) {
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | LBS_NOINTEGRALHEIGHT,
x, y + 20, 300, 120, hWnd, (HMENU)IDC_LIST_CONNECTIONS, hInst, NULL);
/* Graph area - between Connections and ETCP Metrics */
y += 140;
// app->hGraphWnd = CreateWindowA("STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
// 10, y, GRAPH_WIDTH, GRAPH_HEIGHT, hWnd, (HMENU)IDC_GRAPH, hInst, app);
app->hGraphWnd = CreateWindowExA(
WS_EX_CLIENTEDGE,
"ETCPMonGraph", "",
WS_CHILD | WS_VISIBLE | WS_BORDER,
10, y, GRAPH_WIDTH, GRAPH_HEIGHT,
hWnd, (HMENU)IDC_GRAPH, hInst, app);
/* Channel list - grid blocks below graph */
y += GRAPH_HEIGHT + 5;
const char* channel_short_names[] = {
"RTT-L", "RTT10", "RTT100", "Jitter",
"Retrns", "ACKs", "Inflght", "Bytes/s"
};
int block_w = 200;
int block_h = 50;
int cols = 4;
int spacing = 5;
for (int i = 0; i < GRAPH_METRICS_COUNT; i++) {
int col = i % cols;
int row = i / cols;
int bx = 10 + col * (block_w + spacing);
int by = y + row * (block_h + spacing);
app->hChannelName[i] = CreateWindowExA(0, "STATIC", channel_short_names[i],
WS_CHILD | WS_VISIBLE,
bx, by, block_w, 16, hWnd, (HMENU)(UINT_PTR)(IDC_CH_NAME_0 + i), hInst, NULL);
app->hChannelValue[i] = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY,
bx, by + 16, block_w, 18, hWnd, (HMENU)(UINT_PTR)(IDC_CH_VALUE_0 + i), hInst, NULL);
app->hChannelCheck[i] = CreateWindowExA(0, "BUTTON", "",
WS_CHILD | WS_VISIBLE | BS_CHECKBOX | BST_CHECKED,
bx, by + 34, 16, 14, hWnd, (HMENU)(UINT_PTR)(IDC_CH_CHECK_0 + i), hInst, NULL);
}
int channel_grid_h = ((GRAPH_METRICS_COUNT + cols - 1) / cols) * (block_h + spacing) - spacing;
y += channel_grid_h;
/* ETCP Metrics group */
y += 150;
y = 485;
CreateWindowExA(0, "BUTTON", "ETCP Metrics",
WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
x, y, 430, 220, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
@ -265,8 +328,8 @@ static void CreateControls(struct etcpmon_app* app) {
WS_CHILD | WS_VISIBLE | ES_READONLY,
mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_ETCP_LINKS, hInst, NULL);
/* TUN Metrics group */
x = 460; y = 240;
/* TUN Metrics group - right of ETCP Metrics */
x = 460; y = 485;
CreateWindowExA(0, "BUTTON", "TUN Metrics",
WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
x, y, 430, 140, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
@ -312,14 +375,14 @@ static void CreateControls(struct etcpmon_app* app) {
mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_ERRS, hInst, NULL);
/* Links list */
y = 470;
y = 715;
CreateWindowExA(0, "STATIC", "Links:",
WS_CHILD | WS_VISIBLE,
10, y, 100, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hListLinks = CreateWindowExA(WS_EX_CLIENTEDGE, "LISTBOX", "",
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | LBS_NOINTEGRALHEIGHT,
10, y + 20, 880, 120, hWnd, (HMENU)IDC_LIST_LINKS, hInst, NULL);
10, y + 20, 880, 100, hWnd, (HMENU)IDC_LIST_LINKS, hInst, NULL);
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
@ -476,6 +539,21 @@ static void on_connected(void* user_data) {
etcpmon_client_request_list(app->client);
}
void etcpmon_gui_update_graph(struct etcpmon_app* app, struct etcpmon_rsp_metrics* metrics) {
if (!app || !metrics) return;
if (app->hGraphWnd) {
InvalidateRect(app->hGraphWnd, NULL, FALSE);
}
if (app->client) {
struct metrics_history* h = etcpmon_client_get_history(app->client);
if (h && h->count > 0) {
int last_idx = (h->head - 1 + GRAPH_HISTORY_SIZE) % GRAPH_HISTORY_SIZE;
UpdateChannelValues(app, last_idx);
}
}
}
static void on_disconnected(void* user_data) {
@ -508,7 +586,10 @@ static void on_metrics(struct etcpmon_rsp_metrics* metrics,
struct etcpmon_link_metrics* links,
uint8_t links_count, void* user_data) {
struct etcpmon_app* app = (struct etcpmon_app*)user_data;
if (app) {
etcpmon_gui_update_metrics(app, metrics, links, links_count);
etcpmon_client_add_to_history(app->client, metrics);
}
}
static void on_error(const char* msg, void* user_data) {
@ -615,6 +696,7 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
metrics->tun.write_errors);
/* Update links list */
if (app->hListLinks) {
SendMessage(app->hListLinks, LB_RESETCONTENT, 0, 0);
for (uint8_t i = 0; i < links_count; i++) {
char display[256];
@ -637,6 +719,12 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
}
}
if (app->hGraphWnd) {
InvalidateRect(app->hGraphWnd, NULL, FALSE);
UpdateWindow(app->hGraphWnd); // Force immediate paint
}
}
void etcpmon_gui_clear_metrics(struct etcpmon_app* app) {
if (!app) return;
@ -658,6 +746,9 @@ void etcpmon_gui_clear_metrics(struct etcpmon_app* app) {
SetDlgItemTextA(app->hWndMain, IDC_EDIT_TUN_READ_ERRS, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_TUN_WRITE_ERRS, "");
if (app->hListLinks) {
SendMessage(app->hListLinks, LB_RESETCONTENT, 0, 0);
}
SendMessage(app->hListConnections, LB_RESETCONTENT, 0, 0);
}

47
tools/etcpmon/etcpmon_gui.h

@ -20,6 +20,9 @@ struct etcpmon_conn_info;
struct etcpmon_rsp_metrics;
struct etcpmon_link_metrics;
/* Graph constants */
#include "etcpmon_graph.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -59,6 +62,37 @@ extern "C" {
/* Link list control ID */
#define IDC_LIST_LINKS 400
/* Graph control IDs */
#define IDC_GRAPH 500
#define IDC_STATIC_GRAPH 501
#define IDC_LIST_CHANNELS 502
/* Channel block IDs - 8 channels, 4 columns x 2 rows */
#define IDC_CH_NAME_0 510
#define IDC_CH_VALUE_0 520
#define IDC_CH_CHECK_0 530
#define IDC_CH_NAME_1 511
#define IDC_CH_VALUE_1 521
#define IDC_CH_CHECK_1 531
#define IDC_CH_NAME_2 512
#define IDC_CH_VALUE_2 522
#define IDC_CH_CHECK_2 532
#define IDC_CH_NAME_3 513
#define IDC_CH_VALUE_3 523
#define IDC_CH_CHECK_3 533
#define IDC_CH_NAME_4 514
#define IDC_CH_VALUE_4 524
#define IDC_CH_CHECK_4 534
#define IDC_CH_NAME_5 515
#define IDC_CH_VALUE_5 525
#define IDC_CH_CHECK_5 535
#define IDC_CH_NAME_6 516
#define IDC_CH_VALUE_6 526
#define IDC_CH_CHECK_6 536
#define IDC_CH_NAME_7 517
#define IDC_CH_VALUE_7 527
#define IDC_CH_CHECK_7 537
/* Main application structure */
struct etcpmon_app {
HINSTANCE hInstance;
@ -95,6 +129,15 @@ struct etcpmon_app {
/* Links list */
HWND hListLinks;
/* Graph controls (managed by graph module) */
HWND hGraphWnd;
HWND hChannelName[GRAPH_METRICS_COUNT];
HWND hChannelValue[GRAPH_METRICS_COUNT];
HWND hChannelCheck[GRAPH_METRICS_COUNT];
int graph_cursor_x;
int graph_cursor_y;
int graph_cursor_active;
/* Client state - pointer to actual client structure */
struct etcpmon_client* client;
@ -132,6 +175,10 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
/* Clear metrics display */
void etcpmon_gui_clear_metrics(struct etcpmon_app* app);
/* Update graph with new metrics */
void etcpmon_gui_update_graph(struct etcpmon_app* app,
struct etcpmon_rsp_metrics* metrics);
#ifdef __cplusplus
}
#endif

Loading…
Cancel
Save