You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

237 lines
11 KiB

/**
* @file etcp_api.h
* @brief API для приёма-передачи пакетов через ETCP (per-instance bindings)
*
* Основные функции:
* - etcp_send() - отправить пакет в очередь normalizer
* - etcp_bind() - подписаться на пакеты с определенным ID
* - etcp_int_recv() - коллбэк для сбора пакетов из всех подключений
* !!! для обычной отправки-приёма между узлами используем более универсальный модушь etcp_router.
* это в первую очередь - апи для использования etcp-router-ом
*
* Формат кодограмм: <cmd 1 byte> <data ... n bytes>
* cmd = 0 - пакет для передачи адресату
* cmd = 1 - модуль обмена роутинг-таблицами
*/
#ifndef ETCP_API_H
#define ETCP_API_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#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_NAT_DETECTION 0x02 // NAT-детекция (STUN-like ping через третий узел)
#define ETCP_ID_SVC_ROUTE 0x03 // Транспорт роутера (etcp_router)
#define ETCP_ID_NTP_TIME 0x04 // NTP time sync P2P
#define ETCP_ID_BROADCAST 0x05 // Broadcast messages between peers
// === 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_SERVER 0x04 // TCP proxy server: принимает CONNECT/DATA от клиентов
#define ETCP_RT_ID_TCP_PROXY_CLIENT 0x08 // TCP proxy client: принимает DATA/CLOSE/ERROR/FIN от сервера
#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_MEDIA_DELIVERY 0x07 // распространение медиа (аудио/видео стриминг)
#define ETCP_RT_ID_CONN_MGR 0x11 // Connection Manager — management connections
#define ETCP_RT_ID_NCD_CONTROL 0x12 // node_conn_direct — CLOSE / KEEP_ALIVE control
#define ETCP_RT_ID_ADMIN_KEY 0x32 // chat_admin — передача канального приватного ключа (encrypted+signed)
#define ETCP_RT_ID_DM 0x34 // dm_core — прямой p2p чат (msg/ack/hello)
#define ETCP_RT_ID_DM_MAILBOX 0x35 // dm_mailbox — offline-хранение на storage-узлах (put/pull/ack)
#define ETCP_RT_ID_CALL 0x36 // call — P2P аудио-звонок (сигналинг + медиа)
// 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 ETCP_LINK;
struct ETCP_SOCKET;
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 conn ETCP соединение от которого получен пакет
* @param entry Элемент очереди с данными пакета
*
* @note Коллбэк должен освободить entry через queue_entry_free()
* и dgram через queue_dgram_free() после обработки
*
* @note Формат кодограммы для etcp_route_send:
* entry->dgram[0] = svc_id (напр. ETCP_RT_ID_MEDIA_DELIVERY=0x07).
* При приёме router_deliver предваряет payload байтом svc_id:
* entry->dgram[0]=svc_id, entry->dgram[1..]=payload (исходный dgram).
* Если payload содержит cmd+subcmd (двухуровневый, как conn_mgr),
* subcmd в entry->dgram[2]. Если одноуровневый (media_delivery),
* subcmd в entry->dgram[1].
*/
typedef void (*etcp_recv_fn)(struct ETCP_CONN* conn, struct ll_entry* entry);
// Forward declaration
struct ETCP_CONN;
struct UTUN_INSTANCE;
struct TOPO_GROUP_NODE;
// Per-connection callback event types (bitmask)
#define ETCP_CBK_EVENT_INIT (1 << 0)
#define ETCP_CBK_EVENT_REINIT (1 << 1)
#define ETCP_CBK_EVENT_UP (1 << 2)
#define ETCP_CBK_EVENT_DOWN (1 << 3)
#define ETCP_CBK_EVENT_NODE_CHANGED (1 << 4)
typedef void (*etcp_cbk_fn)(struct ETCP_CONN* conn, int event, void* arg);
struct etcp_cbk_entry {
etcp_cbk_fn fn;
void* arg;
int event_mask;
struct etcp_cbk_entry* next;
};
void etcp_cbk_fire(struct ETCP_CONN* conn, int event);
// Instance-level callback types (separate from per-connection etcp_cbk_fn in etcp.h)
typedef void (*etcp_inst_cbk_fn)(struct ETCP_CONN* conn, void* arg);
struct etcp_inst_cbk_entry {
etcp_inst_cbk_fn fn;
void* arg;
struct etcp_inst_cbk_entry* next;
};
// ---- Per-connection unified callback API ----
void etcp_conn_add_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg, int event_mask);
void etcp_conn_remove_cbk(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg);
void etcp_conn_update_cbk_mask(struct ETCP_CONN* conn, etcp_cbk_fn fn, void* arg, int event_mask);
// ---- Instance-level callbacks ----
void etcp_add_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_inst_cbk_fn fn, void* arg);
void etcp_remove_new_conn_cbk(struct UTUN_INSTANCE* inst, etcp_inst_cbk_fn fn, void* arg);
// ---- Link status change callback (instance-level) ----
typedef void (*etcp_link_status_cbk_fn)(struct ETCP_CONN* conn, struct ETCP_LINK* link,
int old_state, int old_status, void* arg);
struct etcp_link_status_cbk_entry {
etcp_link_status_cbk_fn fn;
void* arg;
struct etcp_link_status_cbk_entry* next;
};
void etcp_add_link_status_cbk(struct UTUN_INSTANCE* inst, etcp_link_status_cbk_fn fn, void* arg);
void etcp_remove_link_status_cbk(struct UTUN_INSTANCE* inst, etcp_link_status_cbk_fn fn, void* arg);
void etcp_fire_link_status_cbk(struct ETCP_LINK* link, int old_state, int old_status);
// ---- 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_GROUP_NODE* node,
etcp_connect_callback_t cb, void* arg, uint8_t flags);
/**
* @brief Структура bindings для ETCP API (per-instance)
*/
struct ETCP_BINDINGS {
etcp_recv_fn callbacks[ETCP_MAX_BINDINGS]; /**< Массив callbacks, NULL = не установлен */
};
/**
* @brief Отправить пакет в очередь normalizer. первый байт кодограммы - cmd (на приёмной стороне bind выберет обработчик по cmd).
*
* @param conn ETCP соединение
* @param entry Элемент очереди с данными для отправки
* @return 0 при успехе, -1 при ошибке
*
* @note Функция забирает ownership entry — вызывающий код не должен
* ни освобождать, ни читать entry после вызова: если очередь
* normalizer'а пуста, entry освобождается СИНХРОННО внутри этого
* вызова (queue_data_put → callback → queue_entry_free). Любые
* нужные поля entry надо сохранять до etcp_send().
*/
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);
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);
/* Socket property change events (instance-level) */
#define ETCP_SOCKET_EVENT_ADDR_CHANGED (1 << 0)
#define ETCP_SOCKET_EVENT_STATUS_CHANGED (1 << 1)
typedef void (*etcp_socket_cbk_fn)(struct ETCP_SOCKET* sock, int event, void* arg);
struct etcp_socket_cbk_entry {
etcp_socket_cbk_fn fn;
void* arg;
int event_mask;
struct etcp_socket_cbk_entry* next;
};
void etcp_add_socket_cbk(struct UTUN_INSTANCE* inst, etcp_socket_cbk_fn fn, void* arg, int event_mask);
void etcp_remove_socket_cbk(struct UTUN_INSTANCE* inst, etcp_socket_cbk_fn fn, void* arg);
void etcp_socket_cbk_fire(struct ETCP_SOCKET* sock, int event);
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