diff --git a/src/chat/chat_channel.c b/src/chat/chat_channel.c index a2fbdb36..d3ed0f21 100644 --- a/src/chat/chat_channel.c +++ b/src/chat/chat_channel.c @@ -7,6 +7,7 @@ #include "chat_core_priv.h" #include "group_avatar.h" #include "chat_event.h" +#include "chat_feedback.h" #include "chat_setting.h" #include "../utun_instance.h" @@ -61,6 +62,7 @@ static int channel_sign_join(const uint8_t* ch_x25519, const uint8_t* ch_ed25519 void chat_core_ensure_channel_ready(struct UTUN_INSTANCE* inst, const char* ch_id) { struct chat_core_ctx* cc = CC(inst); if (!cc || !cc->initialized || !ch_id || !ch_id[0]) return; + if (chat_feedback_ensure_channel(inst, ch_id) < 0) return; if (si_find(inst, ch_id)) return; char tbl_msg[80]; msg_table_name(ch_id, tbl_msg, sizeof(tbl_msg)); diff --git a/src/chat/chat_sync.c b/src/chat/chat_sync.c index ac3bcf0b..03c2ec93 100644 --- a/src/chat/chat_sync.c +++ b/src/chat/chat_sync.c @@ -14,6 +14,7 @@ #include "../../lib/json_flat.h" #include "member_sync.h" #include "merkle_sync.h" +#include "chat_feedback.h" #include "../utun_instance.h" #include "../transport_layer/etcp_api.h" @@ -537,12 +538,21 @@ static void cs_resume_db_sync(struct chat_sync* cs, const char* ch_id) { if (si) db_sync_instance_set_gated(si, 0); } +/* Подтверждение feedback не управляет готовностью участников или истории сообщений. */ +static void cs_feedback_done(uint64_t peer, const char* channel, int result, void* arg) { + (void)arg; + DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "%s: feedback sync ch=%s peer=%016llx result=%d", + CS_ID, channel, (unsigned long long)peer, result); +} + static void _on_member_sync_done(uint64_t peer, const char* ns, int result, void* arg) { struct chat_sync* cs = (struct chat_sync*)arg; if (result == MT_OK) { struct channel_cache* ch = cs ? cs_find(cs, ns) : NULL; if (ch) ch->synced = CS_SYNC_DONE; cs_resume_db_sync(cs, ns); + if (cs && merkle_sync_start(cs->inst, MT_DATA_FEEDBACK, peer, ns, cs_feedback_done, cs) < 0) + DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "%s: feedback sync unavailable ch=%s peer=%016llx", CS_ID, ns, (unsigned long long)peer); } DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: member_sync %s ns=%s peer=%016llx", CS_ID, result == MT_OK ? "OK" : "FAIL", ns, (unsigned long long)peer); @@ -753,6 +763,10 @@ int chat_sync_init(struct UTUN_INSTANCE* inst) { DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: member synchronization initialization failed", CS_ID); inst->chat_sync = NULL; u_free(cs); return -1; } + if (chat_feedback_init(inst) < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: feedback initialization failed", CS_ID); + member_sync_destroy(inst); inst->chat_sync = NULL; u_free(cs); return -1; + } if (group_avatar_init(inst) < 0) { member_sync_destroy(inst); inst->chat_sync = NULL; u_free(cs); return -1; } diff --git a/src/routing_layer/topo_node_sqlite.c b/src/routing_layer/topo_node_sqlite.c index bc59c903..c2d74619 100644 --- a/src/routing_layer/topo_node_sqlite.c +++ b/src/routing_layer/topo_node_sqlite.c @@ -491,6 +491,10 @@ int topo_node_sqlite_channel_delete(sqlite3* db, const char* channel_id) { sqlite3_exec(db, sql, NULL, NULL, NULL); snprintf(sql, sizeof(sql), "DROP TABLE IF EXISTS \"%s\"", msg_full); sqlite3_exec(db, sql, NULL, NULL, NULL); + snprintf(sql, sizeof(sql), "DROP TABLE IF EXISTS \"feedback_%s\"", msg_tbl); + if (sqlite3_exec(db, sql, NULL, NULL, NULL) != SQLITE_OK) { + DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: delete channel=%s: %s", channel_id, sqlite3_errmsg(db)); return -1; + } /* 2. delete channels row (вместе с канальными privkey) */ sqlite3_stmt* st = NULL;