Specify router local delivery, callbacks, flow control and reset contracts
This commit is contained in:
1 parent
3bd9b964fa
commit
09e620e12a
1 file changed
+40
-22
@@ -20,10 +20,11 @@
|
||||
// Изменяемый список находится вне end-to-end подписи/шифрования. Получатель
|
||||
// проверяет его границы, уникальность, первый ID=src и последний ID=ETCP peer.
|
||||
// Это защита от ошибок маршрутизации, а не доказательство пути от недоверенного пира.
|
||||
// flags: bit7=START, bit6=RST, bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE
|
||||
// flags: bit7=START, bit6=RST, bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE, bit0=RECEIVE_BUSY (ACK)
|
||||
// reset_id/peer_reset_id — идентификаторы отправителя/получателя во всех пакетах.
|
||||
// START=HELLO, RST=CHALLENGE, START|RST=CONFIRM; challenge используется только в handshake.
|
||||
// ACK-пакет: тот же заголовок, seq=rx_seq, payload_len=0
|
||||
// ACK-пакет: тот же заголовок, seq=rx_seq, payload_len=0; RECEIVE_BUSY поддерживает ожидание без продвижения seq.
|
||||
// Локальная доставка через etcp_route_send выполняется синхронно без сетевого канала/crypto/receive_ready.
|
||||
#ifndef ETCP_ROUTER_H
|
||||
#define ETCP_ROUTER_H
|
||||
|
||||
@@ -48,7 +49,7 @@ struct SVC_ROUTE_HDR {
|
||||
uint64_t src_node_id;
|
||||
uint32_t seq; // data: tx_seq; ACK: rx_seq (ожидаемый seq)
|
||||
uint8_t svc_id; // идентификатор сервиса
|
||||
uint8_t flags; // bit7=START, bit6=RST, bit3=SIGNED, bit2=ENCRYPTED, bit1=CLOSE
|
||||
uint8_t flags; // ROUTER_FLAG_*; RECEIVE_BUSY допустим только в ACK без payload
|
||||
uint16_t timestamp; // часы отправителя (0.1ms), для RTT; ACK: эхо последнего data-пакета
|
||||
uint64_t reset_id; // случайный идентификатор локального экземпляра router_conn
|
||||
uint64_t peer_reset_id; // идентификатор экземпляра получателя (0 только в HELLO)
|
||||
@@ -128,12 +129,12 @@ struct ETCP_ROUTER_CONN {
|
||||
uint32_t tx_seq; // следующий seq для отправки
|
||||
uint32_t tx_sent; // граница фактически отправленных пакетов (ACK <= tx_sent)
|
||||
uint32_t rx_seq; // ожидаемый seq для сборки (next expected)
|
||||
uint32_t tx_acked; // сколько наших пакетов подтвердил remote (для inflight)
|
||||
uint32_t tx_acked; // следующий seq после подтверждённых пакетов, модульный uint32, не накопленный счётчик
|
||||
uint32_t last_sent_ack_seq; // последний отправленный ACK (= rx_seq на момент отправки)
|
||||
uint64_t last_ack_sent_tb; // время отправки последнего ACK (timebase 0.1ms)
|
||||
|
||||
struct UTUN_INSTANCE* inst;
|
||||
struct ETCP_CONN* recv_conn; // физический conn последнего принятого data-пакета (для deliver, не NULL)
|
||||
struct ETCP_CONN* recv_conn; // заимствованный транспорт последнего DATA; NULL после reset/уничтожения транспорта
|
||||
struct ll_queue* recv_q; // reorder очередь: hash по seq (4 байта, offset 0)
|
||||
void* ack_timer; // периодический таймер (10ms при consumer_ack)
|
||||
void* idle_ack_timer; // idle таймер (дослать последний ack)
|
||||
@@ -160,7 +161,7 @@ struct ETCP_ROUTER_CONN {
|
||||
// Ретрансмиты: inflight очередь
|
||||
struct ll_queue* inflight_q; // хеш по seq (4 байта), непрерывный блок без SACK
|
||||
void* retrans_timer; // таймер проверки застоя ACK
|
||||
uint64_t last_ack_changed_tb; // когда tx_acked последний раз менялся (0.1ms)
|
||||
uint64_t last_ack_changed_tb; // отсчёт RTO: продвижение ACK, принятый RECEIVE_BUSY или начало повторного прохода (0.1ms)
|
||||
|
||||
// Очередь приёма входящего трафика (между сетью и recv_q)
|
||||
struct ll_queue* incoming_q; // FIFO очередь входящих пакетов
|
||||
@@ -176,7 +177,7 @@ struct ETCP_ROUTER_CONN {
|
||||
uint32_t c_retrans_done; // число выполненых ретрансмитов
|
||||
uint32_t c_dup_dropped; // дропнуто дубликатов seq
|
||||
uint32_t c_oob_dropped; // дропнуто out-of-bounds seq
|
||||
uint32_t c_stale_ack; // устаревших ACK
|
||||
uint32_t c_stale_ack; // ACK вне диапазона или без продвижения seq, включая допустимый повтор RECEIVE_BUSY
|
||||
uint32_t c_sign_fail; // signature verification failures
|
||||
struct route_tx_meter delivery; // первые подтверждения исходного payload, без wire overhead
|
||||
};
|
||||
@@ -191,7 +192,9 @@ struct ETCP_ROUTER_TX_STATS {
|
||||
int ready, no_route, receive_busy, probing;
|
||||
};
|
||||
|
||||
/* Только uasync. 0 — снимок, 1 — канал отсутствует/закрыт, -1 — неверные аргументы. Канал не создаёт. */
|
||||
/* Только uasync. 0 — снимок, 1 — канал отсутствует/закрыт (out обнулён), -1 — неверные аргументы/время.
|
||||
* now_us — монотонные микросекунды, не раньше последнего учтённого ACK. При -1 out не меняется; канал не создаётся.
|
||||
* ready означает подтверждённый peer_reset_id, отдельно от READY топологии или готовности физического транспорта. */
|
||||
int etcp_router_tx_stats(struct UTUN_INSTANCE *inst, uint64_t group, uint64_t peer, uint8_t svc,
|
||||
uint64_t now_us, struct ETCP_ROUTER_TX_STATS *out);
|
||||
|
||||
@@ -223,7 +226,7 @@ struct ROUTER_INFLIGHT {
|
||||
struct ll_entry ll; // индекс по seq (4 байта, offset 0)
|
||||
uint32_t seq;
|
||||
uint64_t last_sent_tb; // время последней отправки (0.1ms)
|
||||
uint8_t send_count; // число переотправок
|
||||
uint8_t send_count; // успешные отправки, включая первую; диагностический циклический счётчик
|
||||
uint8_t* dgram; // неизменяемое тело [SVC_ROUTE_HDR][payload][sig?], без visited_ids/count
|
||||
size_t dgram_len;
|
||||
};
|
||||
@@ -239,24 +242,32 @@ struct ETCP_ROUTER_BINDINGS {
|
||||
// 3. Публичное API (для сервисов)
|
||||
// ====================================================================
|
||||
|
||||
// Инициализация: etcp_bind(ETCP_ID_SVC_ROUTE) + очистка bindings + создание router_conns
|
||||
// Первичная инициализация ядра: очистить bindings, создать router_conns, etcp_bind(ETCP_ID_SVC_ROUTE); 0/-1.
|
||||
// Вызывать один раз до запуска сервисов; после destroy можно инициализировать заново.
|
||||
int etcp_router_init(struct UTUN_INSTANCE* inst);
|
||||
|
||||
// Закрыть каналы, снять обработчик и освободить маршрутизатор.
|
||||
// Снять обработчик, закрыть каналы и очистить все транзитные очереди/таймеры на живых ETCP. Повторный destroy допустим.
|
||||
// До вызова остановить производителей/ожидания сервисов; из callback останавливаемого сервиса ядро не уничтожать.
|
||||
void etcp_router_destroy(struct UTUN_INSTANCE* inst);
|
||||
|
||||
// Зарегистрировать обработчик сервиса
|
||||
// Зарегистрировать/заменить callback; 0/-1. Замена сохраняет receive_ready/crypto policy.
|
||||
// callback=NULL снимает callback, receive_ready и policy, даже если сервиса не было; каналы не закрывает.
|
||||
// Сервис получает владение entry: [26-byte ROUTER_SVC header][payload]. Пустой payload — уведомление close/reset.
|
||||
// conn заимствован на время callback; при локальных событиях синтетический (instance, peer=self), отправлять через него нельзя.
|
||||
// End-to-end src/dst/group читать из заголовка через memcpy; conn может обозначать промежуточного пира.
|
||||
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);
|
||||
|
||||
// Задать обязательные ROUTER_FLAG_ENCRYPTED/SIGNED для зарегистрированного сервиса, в обе стороны.
|
||||
// Проверка входящих данных — до состояния/очередей/receive_ready, только на конечном узле; управляющие пакеты без payload исключены.
|
||||
// Задать обязательные ROUTER_FLAG_ENCRYPTED/SIGNED для зарегистрированного сервиса, в обе стороны сетевого обмена.
|
||||
// Входящие данные проверяются до состояния/очередей/receive_ready, на конечном узле; header-only control исключён.
|
||||
// Доверенная синхронная доставка dst=self обходит crypto policy и даёт rx_flags=0.
|
||||
// Работает в uasync; unbind очищает требование. Возвращает 0 при успехе, -1 при неверном instance/сервисе/маске.
|
||||
int etcp_router_require_crypto(struct UTUN_INSTANCE* inst, uint8_t svc_id, uint8_t flags);
|
||||
|
||||
// Проверяется до доставки/ACK. 0 оставляет пакет в recv_q, сохраняя порядок; CLOSE не блокируется.
|
||||
// ready получает заимствованный проверенный payload и работает в uasync без I/O. NULL снимает ограничение.
|
||||
// ready получает заимствованный plaintext, работает в uasync без I/O и изменения состояния/закрытия роутера.
|
||||
// NULL снимает ограничение; для уже приостановленных каналов вызвать resume_receive отдельно. Локальная доставка не проверяется.
|
||||
void etcp_router_set_receive_ready(struct UTUN_INSTANCE* inst, uint8_t svc_id,
|
||||
int (*ready)(struct UTUN_INSTANCE*, uint64_t, uint64_t, const uint8_t*, size_t));
|
||||
// Продолжение отложено; канал не создаётся, waiter/arg сервиса не сохраняются.
|
||||
@@ -264,8 +275,11 @@ void etcp_router_resume_receive(struct UTUN_INSTANCE* inst, uint64_t group, uint
|
||||
|
||||
// Отправить сервисный пакет (авто-conn, seq, inflight-контроль через send_q).
|
||||
// Принимает владение entry во всех исходах, включая ошибку.
|
||||
// entry->dgram = svc_id[1] || payload; 0=принято в очередь, <0=ошибка, не подтверждение доставки.
|
||||
// force разрешает превысить лимит числа пакетов в send_q.
|
||||
// entry->dgram = svc_id[1] || непустой payload; mode должен содержать только допустимые биты.
|
||||
// Для удалённого узла 0=принято в send_q, не подтверждение доставки. Предел включает wire-header, crypto и полный visited-list.
|
||||
// Для dst=self callback вызывается синхронно, 0=доставлено callback, -1=размер/нет обработчика/ошибка памяти.
|
||||
// В self-ветке нет канала, inflight, receive_ready и crypto; rx_flags=0, payload до UINT16_MAX-ROUTER_SVC_HDR_SIZE байт.
|
||||
// force разрешает превысить лимит числа пакетов сетевой send_q; для self не используется.
|
||||
// mode — битовая маска ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT (см. route_crypto.h), 0 = обычный пакет.
|
||||
int etcp_route_send(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t dst_node_id, struct ll_entry* entry, int force, int mode);
|
||||
|
||||
@@ -285,14 +299,17 @@ struct ETCP_ROUTER_PATH etcp_router_get_path(struct UTUN_INSTANCE* inst, uint64_
|
||||
|
||||
// Отправить данные с авто-seq и контролем inflight
|
||||
// data: payload без svc_id, mode: ROUTE_CRYPTO_SIGN / ROUTE_CRYPTO_ENCRYPT (0 = обычный)
|
||||
// Копирует data; 0=принято в очередь, <0=ошибка. Доставка подтверждается отдельно протоколом.
|
||||
// Копирует непустой data; 0=принято в очередь, <0=ошибка. Доставка подтверждается отдельно протоколом.
|
||||
// Это сетевой API rconn; для синхронной локальной доставки использовать etcp_route_send.
|
||||
int etcp_router_conn_send(struct ETCP_ROUTER_CONN* rconn,
|
||||
const uint8_t* data, size_t len, int mode);
|
||||
|
||||
// Закрыть канал и уведомить сервис. После вызова rconn использовать нельзя.
|
||||
// Снять канал с реестра, затем синхронно уведомить сервис и очистить ресурсы; память освобождается отложенно.
|
||||
// Callback может закрывать другие каналы/группу или открыть замену с тем же ключом. После close rconn использовать нельзя.
|
||||
void etcp_router_conn_close(struct ETCP_ROUTER_CONN* rconn);
|
||||
|
||||
// Установить рабочий max_inflight, пересчитывает inflight_limit и state machine
|
||||
// Установить max_inflight (минимум 4), пересчитать inflight_limit и state machine.
|
||||
// В minRTT probe лимит равен 4; reset сессии возвращает default=256.
|
||||
void etcp_router_set_max_inflight(struct ETCP_ROUTER_CONN* rconn, uint16_t new_max);
|
||||
|
||||
// Дождаться порога send_q. h должен быть обнулён и жить до callback/отмены.
|
||||
@@ -305,7 +322,7 @@ void etcp_router_on_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, ui
|
||||
void etcp_router_cancel_send_ready(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id,
|
||||
struct queue_waiter_handle* h);
|
||||
|
||||
// Backpressure: проверить есть ли место в send_q (без регистрации waiter)
|
||||
// Есть ли место в send_q существующего канала; 1/0. Канал не создаёт, его отсутствие даёт 0.
|
||||
int etcp_router_send_q_has_room(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t node_id, uint8_t svc_id);
|
||||
|
||||
// ====================================================================
|
||||
@@ -321,7 +338,8 @@ void etcp_router_close_group(struct UTUN_INSTANCE* inst, uint64_t group_id);
|
||||
// Закрыть логические каналы одного пира в группе.
|
||||
void etcp_router_conn_close_all_for_node(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t remote_node_id);
|
||||
|
||||
// Начать новую локальную сессию для конкретного peer+svc в группе и уведомить сервис.
|
||||
// Сбросить существующий peer+svc: новая локальная эпоха, пустые очереди/seq/метрики, затем уведомление сервиса и HELLO.
|
||||
// Отсутствующий канал не создаётся. Данные, отправленные сервисом из уведомления, относятся к новой сессии.
|
||||
void etcp_router_conn_restart(struct UTUN_INSTANCE* inst, uint64_t group_id, uint64_t remote_node_id, uint8_t svc_id);
|
||||
|
||||
// Удалить все транзитные очереди соединения (вызывается при закрытии ETCP_CONN)
|
||||
|
||||
Reference in new issue
Block a user