Browse Source

chat: gate broadcast on CHANGED, my_name via update_sig, set_online local-only gating

topo_upd
evgeny 2 months ago
parent
commit
4e06db77af
  1. 4
      src/chat/chat_channel.c
  2. 4
      src/chat/chat_core.c
  3. 56
      src/chat/chat_profile.c
  4. 10
      src/chat/chat_sync.c

4
src/chat/chat_channel.c

@ -193,9 +193,11 @@ void chat_core_create_channel(struct chat_channel_create* req) {
int mrc = member_sync_put(g_cc.inst, req->channel_id, myid,
g_cc.inst->my_keys.public_key, g_cc.inst->my_ed25519_pubkey,
join_sig, join_ts, NULL, 0, juser3, my_addrs, my_addr_cnt, NULL, NULL, 0);
if (mrc != 0) {
if (mrc < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: member_sync_put(self) FAILED ch=%s rc=%d",
CC_ID, req->channel_id, mrc);
} else if (mrc & MS_APPLY_CHANGED) {
member_sync_broadcast_one(g_cc.inst, req->channel_id, myid);
}
chat_core_sync_my_addresses();
}

4
src/chat/chat_core.c

@ -669,8 +669,8 @@ int chat_member_tags_commit(struct chat_member_tags* t) {
int rc = member_sync_put(g_cc.inst, t->ch_id, t->node_id, x25, ed, jsig, jts, usig, uts,
uinfo ? uinfo : "", NULL, 0, json, sig, stg);
sqlite3_finalize(st);
if (rc != 0) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: tags_commit — member_sync_put failed rc=%d", CC_ID, rc); return -1; }
member_sync_broadcast_one(g_cc.inst, t->ch_id, t->node_id);
if (rc < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: tags_commit — member_sync_put failed rc=%d", CC_ID, rc); return -1; }
if (rc & MS_APPLY_CHANGED) member_sync_broadcast_one(g_cc.inst, t->ch_id, t->node_id);
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "%s: tags_commit ch=%s nid=0x%016llx ver=%d keys=%d json=%s",
CC_ID, t->ch_id, (unsigned long long)t->node_id, ver, t->key_count, json);

56
src/chat/chat_profile.c

@ -35,54 +35,58 @@ void chat_core_update_my_name(const char* name) {
uint64_t myid = g_cc.my_node_id;
sqlite3_stmt* cs = NULL;
sqlite3_prepare_v2(g_cc.db, "SELECT channel_id, x25519_pubkey, ed25519_pubkey FROM channels", -1, &cs, NULL);
sqlite3_prepare_v2(g_cc.db, "SELECT channel_id FROM channels", -1, &cs, NULL);
if (cs) {
while (sqlite3_step(cs) == SQLITE_ROW) {
const char* ch = (const char*)sqlite3_column_text(cs, 0);
const uint8_t* ch_x25519 = sqlite3_column_blob(cs, 1);
const uint8_t* ch_ed25519 = sqlite3_column_blob(cs, 2);
if (!ch || !ch_x25519 || !ch_ed25519) continue;
if (!ch) continue;
char tbl[80]; peers_table_name(ch, tbl, sizeof(tbl));
char buf[256]; snprintf(buf, sizeof(buf), "SELECT 1 FROM \"%s\" WHERE node_id=?", tbl);
char buf[256]; snprintf(buf, sizeof(buf), "SELECT update_ts FROM \"%s\" WHERE node_id=?", tbl);
sqlite3_stmt* ps = NULL;
if (sqlite3_prepare_v2(g_cc.db, buf, -1, &ps, NULL) == SQLITE_OK) {
if (sqlite3_prepare_v2(g_cc.db, buf, -1, &ps, NULL) != SQLITE_OK) continue;
sqlite3_bind_int64(ps, 1, (sqlite3_int64)myid);
if (sqlite3_step(ps) == SQLITE_ROW) {
uint8_t join_msg[256]; size_t mlen = 0;
memcpy(join_msg + mlen, ch_x25519, 32); mlen += 32;
memcpy(join_msg + mlen, ch_ed25519, 32); mlen += 32;
memcpy(join_msg + mlen, &myid, 8); mlen += 8;
memcpy(join_msg + mlen, g_cc.inst->my_keys.public_key, 32); mlen += 32;
uint64_t join_ts = (uint64_t)ntp_time_get_seconds(g_cc.inst);
memcpy(join_msg + mlen, &join_ts, 8); mlen += 8;
uint8_t new_sig[64]; memset(new_sig, 0, 64);
if (sqlite3_step(ps) != SQLITE_ROW) { sqlite3_finalize(ps); continue; }
uint64_t local_uts = (uint64_t)sqlite3_column_int64(ps, 0);
sqlite3_finalize(ps);
/* join неизменен при смене имени — читаем существующий join_sig/join_ts */
uint8_t join_sig[64]; uint64_t join_ts = 0;
if (topo_node_sqlite_member_get_join(g_cc.db, ch, myid, join_sig, &join_ts) != 0) continue;
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", name);
uint64_t update_ts = (uint64_t)ntp_time_get_seconds(g_cc.inst);
if (update_ts <= local_uts) update_ts = local_uts + 1; /* гарантируем рост ver */
/* update_sig = sign(join_sig || update_ts || userinfo) ключом мембера */
uint8_t umsg[256 + 64 + 8]; size_t ulen = 0;
memcpy(umsg + ulen, join_sig, 64); ulen += 64;
memcpy(umsg + ulen, &update_ts, 8); ulen += 8;
size_t jl = strlen(juser);
memcpy(umsg + ulen, juser, jl + 1); ulen += jl + 1;
uint8_t update_sig[64]; memset(update_sig, 0, 64);
EVP_PKEY* pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
g_cc.inst->my_ed25519_privkey, 32);
if (pkey) {
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
if (mdctx) {
if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey) == 1)
EVP_DigestSign(mdctx, new_sig, &(size_t){64}, join_msg, mlen);
EVP_DigestSign(mdctx, update_sig, &(size_t){64}, umsg, ulen);
EVP_MD_CTX_free(mdctx);
}
EVP_PKEY_free(pkey);
}
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", name);
int r1 = topo_node_sqlite_member_put(g_cc.db, ch, myid, new_sig, join_ts, NULL, 0,
g_cc.inst->my_keys.public_key, g_cc.inst->my_ed25519_pubkey, juser, NULL, NULL, NULL, 0);
if (r1 != 0) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: member_put(my_name) FAILED ch=%s rc=%d", CC_ID, ch, r1);
int r2 = member_sync_put(g_cc.inst, ch, myid, g_cc.inst->my_keys.public_key,
g_cc.inst->my_ed25519_pubkey, new_sig, join_ts, NULL, 0, juser, NULL, 0, NULL, NULL, 0);
if (r2 != 0) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: member_sync_put(my_name) FAILED ch=%s rc=%d", CC_ID, ch, r2);
else member_sync_broadcast_one(g_cc.inst, ch, myid);
g_cc.inst->my_ed25519_pubkey, join_sig, join_ts,
update_sig, update_ts, juser, NULL, 0, NULL, NULL, 0);
if (r2 < 0) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: member_sync_put(my_name) FAILED ch=%s rc=%d", CC_ID, ch, r2);
else if (r2 & MS_APPLY_CHANGED) member_sync_broadcast_one(g_cc.inst, ch, myid);
uint8_t mevt[1 + 64 + 1 + CHAT_MEMBER_DISPLAY_SIZE]; uint8_t cl = (uint8_t)strlen(ch);
mevt[0] = cl; memcpy(mevt + 1, ch, cl); mevt[1 + cl] = 1;
if (chat_core_get_single_member(ch, myid, mevt + 1 + cl + 1) == 0)
chat_event_post(CHAT_EVT_MEMBER_UPDATED, mevt, 1 + cl + 1 + CHAT_MEMBER_DISPLAY_SIZE);
}
sqlite3_finalize(ps);
}
}
sqlite3_finalize(cs);
}
}

10
src/chat/chat_sync.c

@ -378,8 +378,8 @@ static void cs_on_remote_status_changed(uint64_t peer, int online) {
}
static void cs_on_peer_status_changed(uint64_t peer, int online) {
/* 1. Локальная БД */
member_sync_set_online(g_cs->inst, peer, online);
/* 1. Локальная БД (онлайн НЕ в merkle sync — только локальная запись) */
int online_changed = member_sync_set_online(g_cs->inst, peer, online);
/* 2. GUI + online-бар */
int found_in_channel = 0;
@ -397,9 +397,11 @@ static void cs_on_peer_status_changed(uint64_t peer, int online) {
chat_event_post(CHAT_EVT_MEMBER_UPDATED, mevt, 1 + (int)cl + 1 + CHAT_MEMBER_DISPLAY_SIZE);
cs_post_channel_online(g_cs, ch_id);
/* 3. Рассылка дельты всем synced-соседям */
/* 3. Рассылка дельты всем synced-соседям — только если online реально изменился */
if (online_changed) {
uint8_t st = (uint8_t)online;
merkle_sync_push_update(g_cs->inst, g_cs->channels[i].channel_id, peer, 0x01, &st, 1);
}
break;
}
}
@ -435,12 +437,14 @@ static void _on_invite_sync_done(uint64_t peer, const char* ns, int result, void
CS_ID, (void*)sa, (unsigned long long)sa->node_id, sa->ch_id);
} else {
cs_post_channel_online(g_cs, sa->ch_id);
if (member_sync_set_online(g_cs->inst, sa->node_id, 1)) {
uint8_t one = 1;
merkle_sync_push_update(g_cs->inst, sa->ch_id, sa->node_id, 0x01, &one, 1);
DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: invite_sync push_update node=0x%016llx online=1 ch=%s",
CS_ID, (unsigned long long)sa->node_id, sa->ch_id);
}
}
}
u_free(sa);
}

Loading…
Cancel
Save