/** * @file etcp_api.h * @brief API для приёма-передачи пакетов через ETCP (per-instance bindings) * * Основные функции: * - etcp_send() - отправить пакет в очередь normalizer * - etcp_bind() - подписаться на пакеты с определенным ID * - etcp_int_recv() - коллбэк для сбора пакетов из всех подключений * !!! для обычной отправки-приёма между узлами используем более универсальный модушь etcp_router. * это в первую очередь - апи для использования etcp-router-ом * * Формат кодограмм: * cmd = 0 - пакет для передачи адресату * cmd = 1 - модуль обмена роутинг-таблицами */ #ifndef ETCP_API_H #define ETCP_API_H #ifdef __cplusplus extern "C" { #endif #include #include "../lib/ll_queue.h" #define ETCP_MAX_BINDINGS 256 // === Raw ETCP packet IDs (etcp_bind/etcp_send) === #define ETCP_ID_DATA 0x00 // Пакет для передачи адресату #define ETCP_ID_ROUTE_ENTRY 0x01 // Элемент роутинг-таблицы (BGP) #define ETCP_ID_NAT_DETECTION 0x02 // NAT-детекция (STUN-like ping через третий узел) #define ETCP_ID_SVC_ROUTE 0x03 // Транспорт роутера (etcp_router) // === Router-сервисы (etcp_router_bind/etcp_route_send) === #define ETCP_RT_ID_DATA 0x00 // routing.c — маршрутизация данных #define ETCP_RT_ID_NAT 0x02 // NAT трафик между узлами #define ETCP_RT_ID_SVC_ROUTE 0x03 // etcp_router — транспорт роутера #define ETCP_RT_ID_TCP_PROXY 0x04 // TCP proxy (клиент ↔ exit) #define ETCP_RT_ID_UDP_PROXY 0x05 // UDP datagram прокси (client ↔ exit) #define ETCP_RT_ID_ICMP_PROXY 0x06 // ICMP echo прокси (ping через exit) #define ETCP_RT_ID_MSG_TRANSPORT 0x10 // msg_transport — локальный IPC транспорт сообщений #define ETCP_RT_ID_CONN_MGR 0x11 // Connection Manager — management connections #define ETCP_RT_ID_NTP_TIME 0x12 // NTP time sync между узлами // Connection status events (instance-level callback) #define ETCP_CONN_STATUS_NEW 0 // соединение создано #define ETCP_CONN_STATUS_UP 1 // соединение поднялось #define ETCP_CONN_STATUS_DOWN 2 // соединение упало #define ETCP_CONN_STATUS_DELETE 3 // соединение удалено // Forward declarations struct ETCP_CONN; struct UTUN_INSTANCE; typedef void (*etcp_conn_status_fn)(struct ETCP_CONN* conn, int status, void* arg); struct etcp_status_cbk_entry { etcp_conn_status_fn fn; void* arg; struct etcp_status_cbk_entry* next; }; /** * @brief Тип коллбэка для приёма метрик от пира * @param user_ptr пользовательский указатель * @param conn ETCP соединение от которого получены метрики * @param csv CSV-строка метрик * @param csv_len длина строки * @param sig Ed25519 подпись (64 байта) или NULL если ключ неизвестен */ typedef void (*etcp_metrics_fn)(void* user_ptr, struct ETCP_CONN* conn, const uint8_t* csv, uint32_t csv_len, const uint8_t* sig); /** * @brief Тип коллбэка для приёма пакетов * @param conn ETCP соединение от которого получен пакет * @param entry Элемент очереди с данными пакета * * @note Коллбэк должен освободить entry через queue_entry_free() * и dgram через queue_dgram_free() после обработки */ typedef void (*etcp_recv_fn)(struct ETCP_CONN* conn, struct ll_entry* entry); // Forward declaration struct ETCP_CONN; struct UTUN_INSTANCE; struct TOPO_NODEQ; typedef void (*etcp_cbk_fn)(struct ETCP_CONN* conn, void* arg); // ---- Background connection initialization ---- #define ETCP_CONNECT_EARLY 1 #define ETCP_CONNECT_LATE 2 #define ETCP_CONNECT_BGP_READY 4 // BGP-синхронизация завершена typedef void (*etcp_connect_callback_t)(void* arg, struct ETCP_CONN* conn, int type); int etcp_connect(struct UTUN_INSTANCE* instance, struct TOPO_NODEQ* node, etcp_connect_callback_t cb, void* arg, uint8_t flags); /** * @brief Установить callback при создании нового ETCP соединения * * @param instance UTUN instance * @param callback_fn Коллбэк который будет вызван при создании нового соединения * @param arg Аргумент для коллбэка */ void etcp_set_new_conn_cbk(struct UTUN_INSTANCE* instance, etcp_cbk_fn callback_fn, void* arg); /** * @brief Структура bindings для ETCP API (per-instance) */ struct ETCP_BINDINGS { etcp_recv_fn callbacks[ETCP_MAX_BINDINGS]; /**< Массив callbacks, NULL = не установлен */ etcp_metrics_fn on_metrics_rcvd; /**< Callback приёма метрик от пира */ void* metrics_user_ptr; /**< Аргумент для on_metrics_rcvd */ }; /** * @brief Отправить пакет в очередь normalizer. первый байт кодограммы - cmd (на приёмной стороне bind выберет обработчик по cmd). * * @param conn ETCP соединение * @param entry Элемент очереди с данными для отправки * @return 0 при успехе, -1 при ошибке * * @note Функция забирает ownership entry - вызывающий код не должен * освобождать entry после вызова */ int etcp_send(struct ETCP_CONN* conn, struct ll_entry* entry); /** * @brief Подписаться на все пакеты с указанным ID для данного instance * * @param inst UTUN instance * @param id Идентификатор пакета (первый байт кодограммы, cmd) * @param callback Коллбэк для обработки пакетов с этим ID * @return 0 при успехе, -1 при ошибке * * @note ID=0 зарезервирован для обычных пакетов данных * @note Можно зарегистрировать только один коллбэк на каждый ID в пределах instance */ int etcp_bind(struct UTUN_INSTANCE* inst, uint8_t id, etcp_recv_fn callback); /** * @brief Отписаться от пакетов с указанным ID для данного instance * * @param inst UTUN instance * @param id Идентификатор пакета * @return 0 при успехе, -1 если binding не найден */ int etcp_unbind(struct UTUN_INSTANCE* inst, uint8_t id); /** * @brief Установить callback на событие готовности соединения * * После создания подключения надо дождаться conn_ready (соединение инициализировано). * Только после этого можно передавать сообщения. Иначе сообщения могут потеряться. * conn_ready может вызываться несколько раз (после каждого переподключения). * * @param conn ETCP соединение * @param callback_fn Коллбэк который будет вызван при готовности * @param arg Аргумент для коллбэка */ void etcp_conn_set_init_cbk(struct ETCP_CONN* conn, etcp_cbk_fn callback_fn, void* arg); void etcp_conn_set_up_cbk (struct ETCP_CONN* conn, etcp_cbk_fn callback_fn, void* arg); void etcp_conn_set_down_cbk (struct ETCP_CONN* conn, etcp_cbk_fn callback_fn, void* arg); void etcp_conn_add_init_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg); void etcp_conn_remove_init_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg); void etcp_conn_add_up_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg); void etcp_conn_remove_up_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg); void etcp_conn_add_down_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg); void etcp_conn_remove_down_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg); void etcp_add_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_cbk_fn fn, void* arg); void etcp_remove_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_cbk_fn fn, void* arg); void etcp_add_conn_status_cbk(struct UTUN_INSTANCE* inst, etcp_conn_status_fn fn, void* arg); void etcp_remove_conn_status_cbk(struct UTUN_INSTANCE* inst, etcp_conn_status_fn fn, void* arg); void etcp_set_conn_status_cbk(struct UTUN_INSTANCE* inst, etcp_conn_status_fn fn, void* arg); void etcp_set_routing_exchange_state(struct ETCP_CONN* conn, uint8_t new_state); /** * @brief Внутренняя функция etcp: Коллбэк для очередей output ll_queue normalizer * * Собирает пакеты из всех подключений и отправляет в bind->cbk * по ID (первый байт кодограммы). * * @param queue Очередь из которой получен пакет * @param arg Аргумент - указатель на ETCP_CONN * * @note Этот коллбэк устанавливается автоматически при создании * ETCP подключения через pn_init() */ void etcp_int_recv(struct ll_queue* queue, void* arg); #ifdef __cplusplus } #endif #endif // ETCP_API_H