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.
94 lines
5.0 KiB
94 lines
5.0 KiB
// etcp_router.h — Сервисный слой маршрутизации поверх ETCP |
|
// Маршрутизирует сервисные пакеты до целевой ноды, на промежуточных нодах ретранслирует |
|
// Упрощённый TCP поверх ETCP: восстановление порядка, дедупликация, без переповторов |
|
// |
|
// Формат SVC_ROUTE пакета: |
|
// [cmd:1] [dst_node_id:8] [src_node_id:8] [seq:4] [svc_id:1] [payload...] |
|
// ACK-пакет: тот же заголовок, seq=rx_seq, payload_len=0 |
|
#ifndef ETCP_ROUTER_H |
|
#define ETCP_ROUTER_H |
|
|
|
#include <stdint.h> |
|
#include "etcp_api.h" |
|
|
|
#pragma pack(push, 1) |
|
struct SVC_ROUTE_HDR { |
|
uint8_t cmd; // ETCP_ID_SVC_ROUTE (0x03) |
|
uint64_t dst_node_id; |
|
uint64_t src_node_id; |
|
uint32_t seq; // data: tx_seq; ACK: rx_seq (ожидаемый seq) |
|
uint8_t svc_id; // идентификатор сервиса |
|
}; |
|
#pragma pack(pop) |
|
#define SVC_ROUTE_HDR_SIZE sizeof(struct SVC_ROUTE_HDR) // 22 |
|
#define SVC_ROUTE_MAX_BINDINGS 256 |
|
|
|
// Состояние одного логического подключения (remote_node_id + svc_id) |
|
struct ETCP_ROUTER_CONN { |
|
struct ll_entry ll; // data[0..7]=remote_node_id, data[8]=svc_id — хеш-индекс |
|
uint64_t remote_node_id; // = data[0..7] |
|
uint8_t svc_id; // = data[8] |
|
uint16_t last_dgram_ts; // последний timestamp датаграммы (rx или tx, timebase 0.1ms) |
|
|
|
uint32_t tx_seq; // следующий seq для отправки |
|
uint32_t rx_seq; // ожидаемый seq для сборки (next expected) |
|
uint32_t rx_acked; // последний отправленный ACK (= rx_seq на момент отправки) |
|
|
|
struct UTUN_INSTANCE* inst; |
|
struct ll_queue* recv_q; // reorder очередь: hash по seq (4 байта, offset 0) |
|
void* ack_timer; // периодический таймер (100ms) |
|
void* idle_ack_timer; // idle таймер (дослать последний ack) |
|
|
|
struct ll_queue* send_q; // очередь ожидающих отправки (inflight полон) |
|
void* send_resume_timer; // таймер возобновления отправки |
|
uint8_t send_blocked; // 1 = inflight полон, ждём ack/таймер |
|
}; |
|
|
|
#define ROUTER_CONN_HASH_SIZE 256 |
|
#define ROUTER_RECVQ_HASH_SIZE 1024 |
|
#define ROUTER_MAX_INFLIGHT 256 // макс пакетов в полёте (для контроля inflight) |
|
#define ROUTER_ACK_INTERVAL_TB 1000 // интервал ACK: 100ms в timebase (0.1ms) |
|
#define ROUTER_ACK_IDLE_TB 5000 // idle таймаут: 500ms |
|
#define ROUTER_SEND_RESUME_TB 500 // retry интервал send_q: 50ms |
|
|
|
// Флаги в старших битах seq (взаимоисключающие) |
|
#define ROUTER_SEQ_CLOSE_FLAG 0x80000000 // нормальное закрытие conn |
|
#define ROUTER_SEQ_RST_FLAG 0x40000000 // conn не найден (reset) |
|
|
|
// Bindings для сервисов внутри etcp_router (аналогично ETCP_BINDINGS) |
|
struct ETCP_ROUTER_BINDINGS { |
|
etcp_recv_fn callbacks[SVC_ROUTE_MAX_BINDINGS]; |
|
}; |
|
|
|
// Инициализация: etcp_bind(ETCP_ID_SVC_ROUTE) + очистка bindings + создание router_conns |
|
int etcp_router_init(struct UTUN_INSTANCE* inst); |
|
|
|
// Деинициализация |
|
void etcp_router_destroy(struct UTUN_INSTANCE* inst); |
|
|
|
// Зарегистрировать обработчик сервиса |
|
int etcp_router_bind(struct UTUN_INSTANCE* inst, uint8_t svc_id, etcp_recv_fn callback); |
|
int etcp_router_unbind(struct UTUN_INSTANCE* inst, uint8_t svc_id); |
|
|
|
// Отправить сервисный пакет (авто-conn, seq, inflight-контроль через send_q) |
|
int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t dst_node_id, struct ll_entry* entry); |
|
|
|
// Найти/создать состояние seq-подключения по (remote_node_id, svc_id) |
|
struct ETCP_ROUTER_CONN* etcp_router_conn_get(struct UTUN_INSTANCE* inst, |
|
uint64_t remote_node_id, uint8_t svc_id); |
|
|
|
// Отправить данные с авто-seq и контролем inflight |
|
// data: payload без svc_id, flags: битовые флаги (зарезервировано) |
|
int etcp_router_conn_send(struct ETCP_ROUTER_CONN* rconn, |
|
const uint8_t* data, size_t len); |
|
|
|
// Закрыть seq-подключение |
|
void etcp_router_conn_close(struct ETCP_ROUTER_CONN* rconn); |
|
|
|
// Закрыть все router_conn для указанного remote_node_id (peer умер) |
|
void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t remote_node_id); |
|
|
|
// Возвращает количество пакетов в очереди normalizer->input для узла node_id |
|
int etcp_router_input_q_count(struct UTUN_INSTANCE* inst, uint64_t node_id); |
|
|
|
#endif // ETCP_ROUTER_H
|
|
|