154 lines
7.5 KiB
C
154 lines
7.5 KiB
C
/*
|
||
* control_server.h - Control Socket Server for ETCP Monitoring
|
||
*
|
||
* TCP-мониторинг ETCP: init → обработка команд в uasync-потоке → shutdown.
|
||
* Метрики отправляются по запросу; доступ — по IPv4 [control] allow.
|
||
* Один таймер 30 секунд: отсутствие команд в покое либо отсутствие прогресса send при активном TX.
|
||
* Шифрования/аутентификации протокола нет. Общий wire-контракт — etcpmon_protocol.h.
|
||
* Client владеет сокетом, таймером и одним TX-кадром до 32 КиБ. Остальные команды ждут в RX.
|
||
* Начальный список узлов хранится как ID, сериализуется порционно; live-изменения объединяются по ID.
|
||
*/
|
||
|
||
#ifndef CONTROL_SERVER_H
|
||
#define CONTROL_SERVER_H
|
||
|
||
#include "../tools/etcpmon/etcpmon_protocol.h"
|
||
#include "../lib/socket_compat.h"
|
||
#include "../lib/ll_queue.h"
|
||
#include <stdint.h>
|
||
#include <stdio.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* Forward declarations */
|
||
struct UTUN_INSTANCE;
|
||
struct UASYNC;
|
||
struct TOPO_GROUP_NODE;
|
||
struct ll_queue;
|
||
|
||
/* Forward declaration */
|
||
struct control_server;
|
||
|
||
#define CONTROL_NODE_DIRTY_MAX 256
|
||
|
||
/* Client connection state */
|
||
struct control_client {
|
||
struct control_client* next; /* Linked list */
|
||
struct control_server* server; /* Back pointer to server */
|
||
socket_t fd; /* Client socket */
|
||
void* socket_id; /* uasync socket ID */
|
||
|
||
/* Receive buffer */
|
||
uint8_t recv_buffer[ETCPMON_MAX_MSG_SIZE];
|
||
uint16_t recv_len; /* Bytes received so far */
|
||
|
||
/* Selected connection */
|
||
uint64_t selected_peer_id; /* 0 = none selected */
|
||
|
||
struct ll_queue* output_queue; /* Владеет единственным TX-кадром; следующий producer ждёт пустой очереди */
|
||
uint16_t output_offset; /* Отправленные байты головы очереди; dgram/len не меняются */
|
||
void* idle_timer; /* Отсутствие команд либо прогресса TX, см. timer_is_tx */
|
||
uint8_t subscribed_nodes; /* 1 = subscribed to node updates */
|
||
uint8_t write_registered; /* 1 = write events registered in uasync */
|
||
uint8_t read_paused; /* Чтение/разбор ждут пустой TX-очереди */
|
||
uint8_t failed; /* Ошибка producer; владелец callback закроет client после возврата */
|
||
uint8_t timer_is_tx; /* Таймер контролирует прогресс TX, иначе отсутствие команд */
|
||
struct queue_waiter_handle output_waiter; /* Отложенное продолжение; отменить до освобождения client */
|
||
uint64_t* snapshot_ids; /* ID начального списка; никаких заимствованных TOPO_GROUP_NODE* */
|
||
size_t snapshot_count;
|
||
size_t snapshot_index; /* Следующий ID для сериализации */
|
||
uint8_t snapshot_active; /* 1 до постановки NODE_INFO_END */
|
||
uint8_t snapshot_seq; /* seq запроса для NODE_INFO_END */
|
||
uint64_t dirty_ids[CONTROL_NODE_DIRTY_MAX]; /* Последние изменения объединяются по ID */
|
||
uint8_t dirty_removed[CONTROL_NODE_DIRTY_MAX]; /* Последнее событие: 1 = удаление, 0 = обновление */
|
||
size_t dirty_count; /* При переполнении подписчик отключается, события не теряются молча */
|
||
};
|
||
|
||
/* Control server state */
|
||
struct control_server {
|
||
struct UTUN_INSTANCE* instance; /* Parent instance */
|
||
struct UASYNC* ua; /* Async context */
|
||
|
||
/* Listening socket */
|
||
socket_t listen_fd;
|
||
void* listen_socket_id; /* uasync socket ID */
|
||
struct sockaddr_storage bind_addr; /* Bound address */
|
||
|
||
/* Client connections */
|
||
struct control_client* clients; /* Linked list of clients */
|
||
uint32_t client_count; /* Number of connected clients */
|
||
uint32_t max_clients; /* Maximum allowed clients */
|
||
|
||
/* Log file */
|
||
FILE* log_file;
|
||
};
|
||
|
||
/* ============================================================================
|
||
* Public API
|
||
* ============================================================================ */
|
||
|
||
/* Initialize control server
|
||
*
|
||
* Creates listening socket and registers with uasync
|
||
*
|
||
* Parameters:
|
||
* server - Server state structure to initialize
|
||
* ua - uasync context for event handling
|
||
* instance - Parent utun instance
|
||
* bind_addr - Address to bind (from config control_sock)
|
||
* max_clients - Maximum concurrent client connections; 0 selects 8
|
||
*
|
||
* Returns:
|
||
* 0 on success, -1 on error. Server copies bind_addr; caller retains ua/instance/server.
|
||
* With valid arguments, shutdown also cleans resources left by a failed initialization.
|
||
*/
|
||
int control_server_init(struct control_server* server,
|
||
struct UASYNC* ua,
|
||
struct UTUN_INSTANCE* instance,
|
||
struct sockaddr_storage* bind_addr,
|
||
uint32_t max_clients);
|
||
|
||
/* Shutdown control server
|
||
*
|
||
* Closes all client connections and listening socket
|
||
*
|
||
* Parameters:
|
||
* server - Server state to shutdown
|
||
*/
|
||
void control_server_shutdown(struct control_server* server);
|
||
|
||
/* Разобрать накопленные команды всех клиентов в uasync-потоке.
|
||
* Чтение сокета само запускает разбор; отдельный периодический вызов не требуется.
|
||
* Функция лишь повторно разбирает уже принятые данные, не читает сокеты и не рассылает метрики по таймеру.
|
||
*
|
||
* Parameters:
|
||
* server - Server state
|
||
*/
|
||
void control_server_process_updates(struct control_server* server);
|
||
|
||
/* Get number of connected clients
|
||
*
|
||
* Parameters:
|
||
* server - Server state
|
||
*
|
||
* Returns:
|
||
* Number of connected clients
|
||
*/
|
||
uint32_t control_server_get_client_count(const struct control_server* server);
|
||
|
||
/* В uasync-потоке отметить последнее изменение node у подписчиков; node заимствован на время вызова.
|
||
* NODE_INFO содержит 01 04 + topo_node_serialize для UTUN с подсетями; seq=0.
|
||
* Сериализация отложена до освобождения TX, запись заново ищется по ID. Вызывать только для UTUN-группы.
|
||
* Более 256 различных ожидающих ID отключают подписчика с WARN; события не теряются молча. */
|
||
void control_server_notify_node_change(struct control_server* server, struct TOPO_GROUP_NODE* node);
|
||
/* В uasync-потоке отметить удаление UTUN node_id; NODE_REMOVED с seq=0 отправляется после освобождения TX. */
|
||
void control_server_notify_node_removed(struct control_server* server, uint64_t node_id);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* CONTROL_SERVER_H */
|