Browse Source

add sockets to gui

congestion
Evgeny 6 months ago
parent
commit
62a059abdb
  1. 72
      src/control_server.c
  2. 65
      tools/etcpmon/etcpmon_client.c
  3. 19
      tools/etcpmon/etcpmon_client.h
  4. 50
      tools/etcpmon/etcpmon_gui.c
  5. 8
      tools/etcpmon/etcpmon_gui.h
  6. 30
      tools/etcpmon/etcpmon_protocol.h

72
src/control_server.c

@ -88,6 +88,7 @@ static void handle_client_data(struct control_server* server, struct control_cli
static void close_client(struct control_server* server, struct control_client* client);
static void send_conn_list(struct control_server* server, struct control_client* client, uint8_t seq_id);
static void send_socket_list(struct control_server* server, struct control_client* client, uint8_t seq_id);
static void send_metrics(struct control_server* server, struct control_client* client, uint8_t seq_id);
static void send_error(struct control_client* client, uint8_t error_code, const char* msg, uint8_t seq_id);
@ -609,7 +610,7 @@ static void handle_client_data(struct control_server* server, struct control_cli
close_client(server, client);
return;
}
if (hdr->type < ETCPMON_CMD_LIST_CONN || hdr->type > ETCPMON_CMD_DISCONNECT) {
if (hdr->type < ETCPMON_CMD_LIST_CONN || hdr->type > ETCPMON_CMD_LIST_SOCKETS) {
DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Invalid command type from client: 0x%02X", hdr->type);
close_client(server, client);
return;
@ -676,6 +677,10 @@ static void handle_client_data(struct control_server* server, struct control_cli
}
break;
case ETCPMON_CMD_LIST_SOCKETS:
send_socket_list(server, client, req_seq);
break;
case ETCPMON_CMD_DISCONNECT:
if (server->log_file) {
fprintf(server->log_file, "%llu: [LOG] Client requested disconnect\n",
@ -759,6 +764,71 @@ static void send_conn_list(struct control_server* server, struct control_client*
u_free(buffer);
}
static void send_socket_list(struct control_server* server, struct control_client* client, uint8_t seq_id) {
struct UTUN_INSTANCE* instance = server->instance;
uint8_t count = 0;
struct ETCP_SOCKET* sock = instance->etcp_sockets;
while (sock && count < ETCPMON_MAX_CONNECTIONS) {
count++;
sock = sock->next;
}
uint16_t rsp_size = ETCPMON_SOCKET_LIST_SIZE(count);
uint8_t* buffer = (uint8_t*)u_malloc(rsp_size);
if (!buffer) {
DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Failed to allocate socket list buffer");
return;
}
struct etcpmon_msg_header* hdr = (struct etcpmon_msg_header*)buffer;
etcpmon_build_header(hdr, sizeof(struct etcpmon_rsp_socket_list) +
count * sizeof(struct etcpmon_socket_info),
ETCPMON_RSP_SOCKET_LIST,
seq_id);
struct etcpmon_rsp_socket_list* rsp = (struct etcpmon_rsp_socket_list*)(buffer + sizeof(*hdr));
rsp->count = count;
struct etcpmon_socket_info* info = (struct etcpmon_socket_info*)(buffer + sizeof(*hdr) + sizeof(*rsp));
sock = instance->etcp_sockets;
for (uint8_t i = 0; i < count && sock; i++) {
strncpy(info[i].name, sock->name, sizeof(info[i].name) - 1);
info[i].name[sizeof(info[i].name) - 1] = '\0';
info[i].is_ipv6 = (sock->local_addr.ss_family == AF_INET6) ? 1 : 0;
if (sock->local_addr.ss_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)&sock->local_addr;
inet_ntop(AF_INET, &sin->sin_addr, info[i].ip, sizeof(info[i].ip));
info[i].port = ntohs(sin->sin_port);
} else if (sock->local_addr.ss_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&sock->local_addr;
inet_ntop(AF_INET6, &sin6->sin6_addr, info[i].ip, sizeof(info[i].ip));
info[i].port = ntohs(sin6->sin6_port);
} else {
strncpy(info[i].ip, "unknown", sizeof(info[i].ip) - 1);
info[i].ip[sizeof(info[i].ip) - 1] = '\0';
info[i].port = 0;
}
info[i].nat_type = sock->nat_type;
sock = sock->next;
}
if (server->log_file) {
log_hex_data(server->log_file, "TX", buffer, rsp_size);
fprintf(server->log_file, "%llu: [LOG] Sent RSP_SOCKET_LIST count=%d\n",
(unsigned long long)get_timestamp_ms(), count);
fflush(server->log_file);
}
#ifdef _WIN32
send(client->fd, (const char*)buffer, rsp_size, 0);
#else
send(client->fd, buffer, rsp_size, 0);
#endif
u_free(buffer);
}
static void send_metrics(struct control_server* server, struct control_client* client, uint8_t seq_id) {
struct UTUN_INSTANCE* instance = server->instance;

65
tools/etcpmon/etcpmon_client.c

@ -87,6 +87,10 @@ void etcpmon_client_cleanup(struct etcpmon_client* client) {
free(client->conn_list);
client->conn_list = NULL;
}
if (client->socket_list) {
free(client->socket_list);
client->socket_list = NULL;
}
if (client->last_metrics) {
free(client->last_metrics);
client->last_metrics = NULL;
@ -299,6 +303,32 @@ int etcpmon_client_select_connection(struct etcpmon_client* client, uint64_t pee
return 0;
}
int etcpmon_client_request_socket_list(struct etcpmon_client* client) {
if (!client || client->sock == INVALID_SOCKET) return -1;
struct etcpmon_msg_header hdr;
etcpmon_build_header(&hdr, 0, ETCPMON_CMD_LIST_SOCKETS, 0);
if (client->log_file) {
log_hex_data(client->log_file, "TX", (const uint8_t*)&hdr, sizeof(hdr));
fprintf(client->log_file, "%llu: [LOG] CMD_LIST_SOCKETS (seq=0)\n",
(unsigned long long)get_timestamp_ms());
fflush(client->log_file);
}
int sent = send(client->sock, (const char*)&hdr, sizeof(hdr), 0);
if (sent != sizeof(hdr)) {
if (client->log_file) {
fprintf(client->log_file, "%llu: [ERROR] Failed to send CMD_LIST_SOCKETS: %d\n",
(unsigned long long)get_timestamp_ms(), WSAGetLastError());
fflush(client->log_file);
}
return -1;
}
return 0;
}
int etcpmon_client_request_metrics(struct etcpmon_client* client) {
if (!client || client->sock == INVALID_SOCKET) return -1;
@ -440,6 +470,35 @@ static void handle_response(struct etcpmon_client* client, uint8_t msg_type,
break;
}
case ETCPMON_RSP_SOCKET_LIST: {
if (payload_size < sizeof(struct etcpmon_rsp_socket_list)) break;
struct etcpmon_rsp_socket_list* rsp = (struct etcpmon_rsp_socket_list*)payload;
uint8_t count = rsp->count;
if (payload_size < sizeof(*rsp) + count * sizeof(struct etcpmon_socket_info)) break;
if (client->socket_list) {
free(client->socket_list);
}
client->socket_list = (struct etcpmon_socket_info*)malloc(count * sizeof(struct etcpmon_socket_info));
if (client->socket_list) {
memcpy(client->socket_list, payload + sizeof(*rsp), count * sizeof(struct etcpmon_socket_info));
client->socket_count = count;
if (client->log_file) {
fprintf(client->log_file, "%llu: [LOG] RSP_SOCKET_LIST count=%d\n",
(unsigned long long)get_timestamp_ms(), count);
fflush(client->log_file);
}
if (client->on_socket_list) {
client->on_socket_list(client->socket_list, count, client->user_data);
}
}
break;
}
case ETCPMON_RSP_METRICS: {
if (payload_size < sizeof(struct etcpmon_rsp_metrics)) break;
@ -765,9 +824,10 @@ void etcpmon_client_set_callbacks(struct etcpmon_client* client,
void (*on_connected)(void*),
void (*on_disconnected)(void*),
void (*on_conn_list)(struct etcpmon_conn_info*, uint8_t, void*),
void (*on_socket_list)(struct etcpmon_socket_info*, uint8_t, void*),
void (*on_metrics)(struct etcpmon_rsp_metrics*,
struct etcpmon_link_metrics*,
uint8_t, void*),
struct etcpmon_link_metrics*,
uint8_t, void*),
void (*on_error)(const char*, void*),
void* user_data) {
if (!client) return;
@ -775,6 +835,7 @@ void etcpmon_client_set_callbacks(struct etcpmon_client* client,
client->on_connected = on_connected;
client->on_disconnected = on_disconnected;
client->on_conn_list = on_conn_list;
client->on_socket_list = on_socket_list;
client->on_metrics = on_metrics;
client->on_error = on_error;
client->user_data = user_data;

19
tools/etcpmon/etcpmon_client.h

@ -66,6 +66,10 @@ struct etcpmon_client {
struct etcpmon_conn_info* conn_list;
uint8_t conn_count;
/* Socket info cache */
struct etcpmon_socket_info* socket_list;
uint8_t socket_count;
/* Latest metrics */
struct etcpmon_rsp_metrics* last_metrics;
struct etcpmon_link_metrics* last_links;
@ -89,9 +93,10 @@ struct etcpmon_client {
void (*on_connected)(void* user_data);
void (*on_disconnected)(void* user_data);
void (*on_conn_list)(struct etcpmon_conn_info* list, uint8_t count, void* user_data);
void (*on_socket_list)(struct etcpmon_socket_info* list, uint8_t count, void* user_data);
void (*on_metrics)(struct etcpmon_rsp_metrics* metrics,
struct etcpmon_link_metrics* links,
uint8_t links_count, void* user_data);
struct etcpmon_link_metrics* links,
uint8_t links_count, void* user_data);
void (*on_error)(const char* msg, void* user_data);
void* user_data;
@ -128,6 +133,11 @@ int etcpmon_client_is_connected(const struct etcpmon_client* client);
*/
int etcpmon_client_request_list(struct etcpmon_client* client);
/* Request local socket list
* Returns 0 on success, -1 on error
*/
int etcpmon_client_request_socket_list(struct etcpmon_client* client);
/* Select connection to monitor
* Returns 0 on success, -1 on error
*/
@ -160,9 +170,10 @@ void etcpmon_client_set_callbacks(struct etcpmon_client* client,
void (*on_connected)(void*),
void (*on_disconnected)(void*),
void (*on_conn_list)(struct etcpmon_conn_info*, uint8_t, void*),
void (*on_socket_list)(struct etcpmon_socket_info*, uint8_t, void*),
void (*on_metrics)(struct etcpmon_rsp_metrics*,
struct etcpmon_link_metrics*,
uint8_t, void*),
struct etcpmon_link_metrics*,
uint8_t, void*),
void (*on_error)(const char*, void*),
void* user_data);

50
tools/etcpmon/etcpmon_gui.c

@ -36,6 +36,7 @@ static void UpdateUIState(struct etcpmon_app* app);
static void on_connected(void* user_data);
static void on_disconnected(void* user_data);
static void on_conn_list(struct etcpmon_conn_info* list, uint8_t count, void* user_data);
static void on_socket_list(struct etcpmon_socket_info* list, uint8_t count, void* user_data);
static void on_metrics(struct etcpmon_rsp_metrics* metrics,
struct etcpmon_link_metrics* links,
uint8_t links_count, void* user_data);
@ -133,7 +134,7 @@ HWND etcpmon_gui_create_window(struct etcpmon_app* app) {
etcpmon_client_init(app->client);
etcpmon_client_set_callbacks(app->client,
on_connected, on_disconnected,
on_conn_list, on_metrics, on_error,
on_conn_list, on_socket_list, on_metrics, on_error,
app);
}
@ -199,6 +200,15 @@ 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);
/* Sockets list */
CreateWindowExA(0, "STATIC", "Sockets:",
WS_CHILD | WS_VISIBLE,
x + 310, y, 100, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hListSockets = CreateWindowExA(WS_EX_CLIENTEDGE, "LISTBOX", "",
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | LBS_NOINTEGRALHEIGHT,
x + 310, y + 20, 300, 120, hWnd, (HMENU)IDC_LIST_SOCKETS, hInst, NULL);
/* Graph area */
y += 140;
app->hGraphWnd = CreateWindowExA(
@ -790,6 +800,7 @@ static void OnTimer(struct etcpmon_app* app) {
if (app->need_initial_request && app->isConnected) {
etcpmon_client_request_list(app->client);
etcpmon_client_request_socket_list(app->client);
app->need_initial_request = 0;
}
@ -854,6 +865,11 @@ static void on_conn_list(struct etcpmon_conn_info* list, uint8_t count, void* us
}
}
static void on_socket_list(struct etcpmon_socket_info* list, uint8_t count, void* user_data) {
struct etcpmon_app* app = (struct etcpmon_app*)user_data;
etcpmon_gui_update_socket_list(app, list, count);
}
static void on_metrics(struct etcpmon_rsp_metrics* metrics,
struct etcpmon_link_metrics* links,
uint8_t links_count, void* user_data) {
@ -924,6 +940,38 @@ void etcpmon_gui_update_conn_list(struct etcpmon_app* app,
}
}
}
static const char* nat_type_to_string(uint8_t nat_type) {
switch (nat_type) {
case NAT_TYPE_OPEN: return "Open";
case NAT_TYPE_RESTRICTED: return "Restricted";
case NAT_VERIFIED_OPEN: return "Verified-Open";
case NAT_VERIFIED_RESTRICTED: return "Verified-Restricted";
case NAT_VERIFIED_DIRECT: return "Direct";
default: return "Unknown";
}
}
void etcpmon_gui_update_socket_list(struct etcpmon_app* app,
struct etcpmon_socket_info* list,
uint8_t count) {
if (!app || !app->hListSockets) return;
SendMessage(app->hListSockets, LB_RESETCONTENT, 0, 0);
for (uint8_t i = 0; i < count; i++) {
char display[128];
const char* nat_str = nat_type_to_string(list[i].nat_type);
if (list[i].is_ipv6) {
snprintf(display, sizeof(display), "[%s]:%d | NAT: %s",
list[i].ip, list[i].port, nat_str);
} else {
snprintf(display, sizeof(display), "%s:%d | NAT: %s",
list[i].ip, list[i].port, nat_str);
}
SendMessageA(app->hListSockets, LB_ADDSTRING, 0, (LPARAM)display);
}
}
/* Обновляет EDIT только если текст действительно изменился → убирает моргание */
static BOOL UpdateEditIfChanged(HWND hDlg, int nIDDlgItem, const char* fmt, ...)
{

8
tools/etcpmon/etcpmon_gui.h

@ -17,6 +17,7 @@
/* Client structure is defined in etcpmon_client.h */
struct etcpmon_client;
struct etcpmon_conn_info;
struct etcpmon_socket_info;
struct etcpmon_rsp_metrics;
struct etcpmon_link_metrics;
@ -37,6 +38,7 @@ extern "C" {
#define IDC_BTN_CONNECT 102
#define IDC_BTN_DISCONNECT 103
#define IDC_LIST_CONNECTIONS 104
#define IDC_LIST_SOCKETS 106
#define IDC_TIMER_UPDATE 105
/* ETCP Metrics control IDs */
@ -187,6 +189,7 @@ struct etcpmon_app {
HWND hBtnConnect;
HWND hBtnDisconnect;
HWND hListConnections;
HWND hListSockets;
/* ETCP metrics controls */
HWND hEditEtcpName;
@ -325,6 +328,11 @@ void etcpmon_gui_update_conn_list(struct etcpmon_app* app,
struct etcpmon_conn_info* list,
uint8_t count);
/* Update socket list */
void etcpmon_gui_update_socket_list(struct etcpmon_app* app,
struct etcpmon_socket_info* list,
uint8_t count);
/* Update metrics display */
void etcpmon_gui_update_metrics(struct etcpmon_app* app,
struct etcpmon_rsp_metrics* metrics,

30
tools/etcpmon/etcpmon_protocol.h

@ -22,6 +22,15 @@ extern "C" {
* ============================================================================ */
#define ETCPMON_PROTOCOL_VERSION 1
/* NAT types (mirrored from etcp_connections.h for monitor protocol) */
#define NAT_TYPE_UNKNOWN 0
#define NAT_TYPE_OPEN 1
#define NAT_TYPE_RESTRICTED 2
#define NAT_VERIFIED_UNKNOWN 4
#define NAT_VERIFIED_OPEN 5
#define NAT_VERIFIED_RESTRICTED 6
#define NAT_VERIFIED_DIRECT 7
#define ETCPMON_MAX_MSG_SIZE 4096
#define ETCPMON_MAX_CONN_NAME 32
#define ETCPMON_MAX_CONNECTIONS 256
@ -39,10 +48,12 @@ extern "C" {
#define ETCPMON_CMD_SELECT_CONN 0x02 /* Select connection by peer_node_id */
#define ETCPMON_CMD_GET_METRICS 0x03 /* Request metrics for selected */
#define ETCPMON_CMD_DISCONNECT 0x04 /* Disconnect from monitoring */
#define ETCPMON_CMD_LIST_SOCKETS 0x05 /* Request local socket list */
/* Server -> Client responses */
#define ETCPMON_RSP_CONN_LIST 0x81 /* Connection list response */
#define ETCPMON_RSP_METRICS 0x82 /* Metrics response */
#define ETCPMON_RSP_SOCKET_LIST 0x83 /* Socket list response */
#define ETCPMON_RSP_ERROR 0xFF /* Error response */
/* Error codes for RSP_ERROR */
@ -94,6 +105,20 @@ struct etcpmon_rsp_conn_list {
/* Followed by count * struct etcpmon_conn_info */
};
/* RSP_SOCKET_LIST: List of local sockets */
struct etcpmon_socket_info {
char name[ETCPMON_MAX_CONN_NAME]; /* Null-terminated socket name */
char ip[46]; /* Null-terminated IP address string */
uint16_t port; /* Port number (host byte order) */
uint8_t is_ipv6; /* 1 = IPv6, 0 = IPv4 */
uint8_t nat_type; /* NAT type (NAT_TYPE_*, NAT_VERIFIED_*) */
};
struct etcpmon_rsp_socket_list {
uint8_t count; /* Number of sockets */
/* Followed by count * struct etcpmon_socket_info */
};
/* RSP_METRICS: Full metrics for ETCP connection and its links */
/* ETCP Connection metrics */
@ -250,6 +275,11 @@ struct etcpmon_rsp_error {
(sizeof(struct etcpmon_msg_header) + sizeof(struct etcpmon_rsp_conn_list) + \
(count) * sizeof(struct etcpmon_conn_info))
/* Calculate size of socket list response */
#define ETCPMON_SOCKET_LIST_SIZE(count) \
(sizeof(struct etcpmon_msg_header) + sizeof(struct etcpmon_rsp_socket_list) + \
(count) * sizeof(struct etcpmon_socket_info))
/* Calculate size of metrics response */
#define ETCPMON_METRICS_SIZE(links_count) \
(sizeof(struct etcpmon_msg_header) + sizeof(struct etcpmon_rsp_metrics) + \

Loading…
Cancel
Save