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.
124 lines
7.2 KiB
124 lines
7.2 KiB
/* |
|
* chat_sync.h — оркестратор синхронизации чата по ETCP |
|
* |
|
* При поднятии / разрыве ETCP-соединений: |
|
* - обновляет online-статус пиров в БД и GUI |
|
* - запускает member_sync (синхронизацию участников каналов) через merkle_sync |
|
* - управляет кешем каналов (периодический refresh из БД, 30s) |
|
* |
|
* Обслуживает протокол входа в канал (join) между джойнером, connection-узлом и инвайтером: |
|
* JOIN_INFO_REQ → JOIN_INFO_RESP → JOIN_REQUEST → (форвард инвайтеру) → JOIN_READY. |
|
* Полное описание flow и дерева приглашений — в chat_join.h. |
|
* |
|
* Обрабатывает invite-ссылки (chat_sync_connect_from_invite): |
|
* - сохраняет pubkey, join_key и адреса invite-узла в БД (nodes, node_addresses) |
|
* - создаёт TOPO_GROUP, запускает conn_mgr для подключения |
|
* - после поднятия ETCP-соединения запускает join-протокол |
|
* |
|
* Использование: |
|
* 1. chat_sync_init(inst) — вызывается при старте, биндит ETCP_RT_ID_CHAT_SYNC (0x30) |
|
* 2. chat_sync_connect_from_invite(ch_id, node_id, pubkey, addrs, count) — вход по invite |
|
* 3. chat_sync_join_channel(inst, ch_id, target_node_id) — вход через уже подключённый узел |
|
* 4. chat_sync_destroy(inst) — вызывается при завершении |
|
*/ |
|
|
|
#ifndef CHAT_SYNC_H |
|
#define CHAT_SYNC_H |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
#include <stdint.h> |
|
#include <stddef.h> |
|
|
|
struct UTUN_INSTANCE; |
|
struct UASYNC; |
|
|
|
/* etcp service IDs (direct P2P): ETCP_RT_ID_CHAT_SYNC / ETCP_RT_ID_MEMBER_SYNC |
|
* (etcp_bind, см. etcp_api.h) */ |
|
|
|
/* Message types */ |
|
#define CS_MSG_INIT_SYNC 0x01 |
|
#define CS_MSG_INIT_RESP 0x02 |
|
#define CS_MSG_SEND_DATA 0x03 |
|
#define CS_MSG_PUSH 0x04 |
|
#define CS_MSG_ACK_PUSH 0x05 |
|
#define CS_MSG_SYNC_DONE 0x06 |
|
#define CS_MSG_ERROR 0x07 |
|
#define CS_MSG_CHANNEL_INVITE 0x0F /* push-invite: inviter → joiner */ |
|
#define CS_MSG_JOIN_INFO_REQ 0x10 /* joiner → connection: {join_key:8} */ |
|
#define CS_MSG_JOIN_INFO_RESP 0x11 /* connection → joiner: channel info + connection's member record */ |
|
#define CS_MSG_JOIN_REQUEST 0x12 /* joiner → connection: {join_key:8, member...} */ |
|
#define CS_MSG_JOIN_READY 0x13 /* connection → joiner: {group_id:8} */ |
|
#define CS_MSG_SOUND_SETTING 0x14 /* peer → server: {sound_on:1} — per-chat play sound on message */ |
|
|
|
/* Protocol constants */ |
|
#define CS_SEND_DATA_MAX 32 |
|
#define CS_MAX_SPARSE 16 |
|
#define CS_PEER_TIMEOUT_MS 5000 |
|
|
|
/* Sync states per channel */ |
|
#define CS_SYNC_NONE 0 |
|
#define CS_SYNC_IN_PROGRESS 1 |
|
#define CS_SYNC_DONE 2 |
|
|
|
/* ── Public API ── */ |
|
|
|
int chat_sync_init(struct UTUN_INSTANCE* inst); |
|
void chat_sync_destroy(struct UTUN_INSTANCE* inst); |
|
|
|
/* Прямое ETCP-подключение к узлу (pubkey+адреса из БД) */ |
|
void chat_sync_connect_node(struct UTUN_INSTANCE* inst, uint64_t node_id); |
|
|
|
/* Подключиться к пиру по данным invite-ссылки (вызывается из uasync-потока). |
|
join_key — 64-битный ключ входа из ссылки (регистрируется инвайтером на connection-узле). |
|
password может быть NULL — тогда отправляется без пароля (совместимость с v1) */ |
|
void chat_sync_connect_from_invite(struct UTUN_INSTANCE* inst, uint64_t channel_id, uint64_t node_id, |
|
const uint8_t* pubkey_bin, |
|
const uint8_t* addrs_data, int addr_count, |
|
int addrs_data_len, |
|
const char* password, uint64_t join_key); |
|
|
|
/* Пригласить target_node_id в канал ch_id с адресами из invite-ссылки (inviter → joiner). |
|
Принимает pubkey и адреса целевого узла. Если соединения ещё нет — строит TOPO_NODE |
|
с адресами, запускает conn_mgr для подключения, и по conn_up отправляет CS_MSG_CHANNEL_INVITE. |
|
Если соединение уже есть — отправляет CHANNEL_INVITE сразу. |
|
Копирует pubkey_bin и addrs_data (вызывающий может освободить после возврата). |
|
Вызов из любого потока — внутри постит в uasync. */ |
|
void chat_sync_invite_to_channel_with_addrs( |
|
struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id, |
|
const uint8_t* pubkey_bin, const uint8_t* addrs_data, int addr_count, |
|
int addrs_data_len); |
|
|
|
/* Пригласить target_node_id в канал ch_id (inviter → joiner). |
|
Отправляет CS_MSG_CHANNEL_INVITE с полной информацией о канале и своих адресах */ |
|
void chat_sync_invite_to_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id); |
|
|
|
/* Принять входящее приглашение — продолжаем join-протокол (CHANNEL_JOIN → WELCOME) */ |
|
void chat_sync_accept_invite(struct UTUN_INSTANCE* inst, uint64_t channel_id, uint64_t inviter_node_id); |
|
|
|
/* Отклонить входящее приглашение */ |
|
void chat_sync_deny_invite(struct UTUN_INSTANCE* inst, uint64_t channel_id, uint64_t inviter_node_id); |
|
|
|
/* Присоединиться к каналу через уже подключённый узел (uasync-поток). |
|
Соединение с target_node_id должно быть установлено (links_up && initialized). |
|
Протокол: CHANNEL_INFO_REQ → CHANNEL_INFO_RESP → CHANNEL_JOIN → WELCOME. |
|
Канал (DB + TOPO_GROUP) создаётся локально при получении CHANNEL_INFO_RESP. */ |
|
void chat_sync_join_channel(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t target_node_id); |
|
|
|
/* Перезапустить групповые подключения для каналов без активных соединений. |
|
Вызывается из auto_socket при появлении/изменении сетевой связности. */ |
|
void chat_sync_retry_channels_on_socket_change(struct UTUN_INSTANCE* inst); |
|
|
|
/* Немедленно убрать канал из кеша g_cs->channels (локальное удаление канала), |
|
* чтобы cs_on_conn_status не запускал member_sync для удалённого ns до следующего refresh. */ |
|
void chat_sync_on_channel_deleted(struct UTUN_INSTANCE* inst, const char* ch_id); |
|
|
|
/* Разослать всем подключённым пирам канала смену per-chat настройки «play sound on message». */ |
|
void chat_sync_broadcast_sound_setting(struct UTUN_INSTANCE* inst, const char* ch_id, int on); |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
#endif /* CHAT_SYNC_H */
|
|
|