- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
144 lines
6.3 KiB
C
144 lines
6.3 KiB
C
/*
|
||
* ── member_sync — синхронизация участников чата ──
|
||
*
|
||
* Тонкая прослойка над merkle_sync, адаптированная под мемберов каналов.
|
||
* Данные хранятся в таблицах: nodes, node_addresses, peers_<channel_id>.
|
||
* Хеш мембера = SHA256(node_id || x25519 || ed25519 || join_sig || join_ts || addrs).
|
||
*
|
||
* ── Использование ──
|
||
*
|
||
* // разово: инициализация (из chat_sync_init)
|
||
* member_sync_init(inst);
|
||
*
|
||
* // асинхронный запуск синхронизации (из cs_on_conn_up)
|
||
* member_sync_start(inst, peer, ch_id, on_done, ch);
|
||
*
|
||
* // коллбэк: синхронизация завершена
|
||
* static void on_done(uint64_t peer, const char* ch_id, int result, void* arg) {
|
||
* struct channel_cache* ch = (struct channel_cache*)arg;
|
||
* if (result == MT_OK) ch->synced = CS_SYNC_DONE;
|
||
* }
|
||
*
|
||
* // добавление/обновление мембера (из chat_core_create_channel, cs_handle_welcome)
|
||
* member_sync_put(inst, ch_id, node_id, x25519, ed25519, join_sig, join_ts, addrs, ac);
|
||
* // дерево автоматически пересчитано
|
||
*
|
||
* // онлайн-статус (из cs_on_conn_up / cs_on_conn_down)
|
||
* member_sync_set_online(inst, node_id, 1); // online
|
||
* member_sync_set_online(inst, node_id, 0); // offline
|
||
*
|
||
* // удаление мембера
|
||
* member_sync_del(inst, ch_id, node_id);
|
||
*
|
||
* // отмена синхронизации (коллбэк НЕ вызывается)
|
||
* member_sync_cancel(inst, peer, ch_id);
|
||
*
|
||
* // количество мемберов в канале
|
||
* int n = member_sync_count(inst, ch_id);
|
||
*
|
||
* // разово: завершение (из chat_sync_destroy)
|
||
* member_sync_destroy(inst);
|
||
*/
|
||
|
||
#ifndef MEMBER_SYNC_H
|
||
#define MEMBER_SYNC_H
|
||
|
||
#include "merkle_sync.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
|
||
struct UTUN_INSTANCE;
|
||
|
||
/*
|
||
* Инициализировать модуль: создаёт merkle_sync с коллбэками для мемберов
|
||
* (ETCP сервис 0x31), регистрирует _on_node_updated для пересчёта дерева
|
||
* при обновлении node info.
|
||
*/
|
||
int member_sync_init(struct UTUN_INSTANCE* inst);
|
||
|
||
/* Завершить модуль. */
|
||
void member_sync_destroy(struct UTUN_INSTANCE* inst);
|
||
|
||
/*
|
||
* Запустить синхронизацию мемберов канала ch_id с пиром peer.
|
||
* Делегирует в merkle_sync_start().
|
||
*/
|
||
int member_sync_start(struct UTUN_INSTANCE* inst, uint64_t peer,
|
||
const char* ch_id, merkle_sync_done_cb done_cb, void* arg);
|
||
|
||
/*
|
||
* Отменить синхронизацию. Делегирует в merkle_sync_cancel().
|
||
*/
|
||
void member_sync_cancel(struct UTUN_INSTANCE* inst, uint64_t peer, const char* ch_id);
|
||
|
||
/*
|
||
* Добавить/обновить мембера и пересчитать дерево.
|
||
*
|
||
* ch_id — ID канала
|
||
* member_id — node_id участника
|
||
* x25519 — X25519 публичный ключ (32 байта)
|
||
* ed25519 — Ed25519 публичный ключ (32 байта)
|
||
* join_sig — Ed25519 подпись join-сообщения (64 байта)
|
||
* сообщение: ch_x25519(32) || ch_ed25519(32) || node_id(8LE) || x25519(32) || join_ts(8LE)
|
||
* join_ts — NTP-синхронизированное время подписи (unix epoch seconds)
|
||
* userinfo — метаданные узла (имя) в канале
|
||
* addrs_data — адреса в wire-формате: [family:1][ip:4|16][port:2]...
|
||
* addr_count — количество адресов (0 если нет)
|
||
*
|
||
* Пишет только в таблицу peers_<ch_id> (INSERT OR REPLACE).
|
||
* nodes обновляется отдельно через topo_node_sqlite_node_update_verified().
|
||
* Вызывает merkle_sync_recompute_path() для пересчёта дерева.
|
||
*
|
||
* Возвращает 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int member_sync_put(struct UTUN_INSTANCE* inst, const char* ch_id,
|
||
uint64_t member_id, const uint8_t* x25519,
|
||
const uint8_t* ed25519,
|
||
const uint8_t* join_sig, uint64_t join_ts,
|
||
const uint8_t* update_sig, uint64_t update_ts,
|
||
const char* userinfo,
|
||
const uint8_t* addrs_data, int addr_count,
|
||
const char* adm_tags, const uint8_t* adm_tags_sig, int storage);
|
||
|
||
/* Удалить мембера из канала и пересчитать дерево. */
|
||
int member_sync_del(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t member_id);
|
||
|
||
/* Количество мемберов в канале (SELECT COUNT из peers_<ch_id>). */
|
||
int member_sync_count(struct UTUN_INSTANCE* inst, const char* ch_id);
|
||
|
||
/*
|
||
* Установить онлайн-статус узла (nodes.online = 0/1).
|
||
*/
|
||
void member_sync_set_online(struct UTUN_INSTANCE* inst, uint64_t node_id, int online);
|
||
|
||
/* Получить хеш бакета из merkle_tree_hash (для тестов). */
|
||
const uint8_t* member_sync_get_hash(struct UTUN_INSTANCE* inst,
|
||
const char* ch_id, uint8_t level, uint64_t prefix64);
|
||
|
||
/*
|
||
* Коллбэк: узел изменился по инициативе удалённого пира (через MSG_ITEM_UPDATE).
|
||
* Вызывается из uasync-потока. Потребитель (chat_sync) может из него
|
||
* постить GUI-события.
|
||
*/
|
||
typedef void (*member_sync_node_updated_fn)(uint64_t node_id, int online);
|
||
void member_sync_set_node_updated_cb(member_sync_node_updated_fn cb);
|
||
|
||
/*
|
||
* Коллбэк: изменились adm_tags любого узла (включая себя).
|
||
* Вызывается при успешной обработке MSG_ITEM_UPDATE с adm_tags.
|
||
* Многоподписочный — можно добавить несколько подписчиков.
|
||
*/
|
||
typedef void (*node_props_changed_fn)(uint64_t node_id, const char* adm_tags, void* arg);
|
||
void member_sync_add_props_cbk(node_props_changed_fn fn, void* arg);
|
||
void member_sync_remove_props_cbk(node_props_changed_fn fn, void* arg);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
#endif /* MEMBER_SYNC_H */
|