fix chatgui: message format, member notify, chain_hash sync
- on_db_sync_insert: parse JSON {"n":...,"ct":...,"d":...}, store
d→data, n→node_id, ct→content_type with proper chain_hash
(fixes JSON displayed instead of message text)
- chat_core_cursor_open: SELECT chain_hash column
- chat_core_cursor_next: include chain_hash(32) in output record
- cs_handle_send_data: parse chain_hash in received records
(fixes chain_hash mismatch → all sync records were dropped)
- cs_handle_channel_join: post GUI_EVT_MEMBERS_CHANGED
(fixes creator not seeing new member after join)
- cs_handle_welcome: trigger INIT_SYNC with inviter after join
(fixes no message sync after invite join)
This commit is contained in:
1 parent
c4751557b1
commit
2d179ec41d
2 files changed
+57
-11
No files matched your search
@@ -453,7 +453,7 @@ uint32_t chat_core_cursor_open(const char* ch_id) {
|
||||
if (g_cc.cursors[i]) continue;
|
||||
char tbl[80]; msg_table_name(ch_id, tbl, sizeof(tbl));
|
||||
char sql[256]; snprintf(sql, sizeof(sql),
|
||||
"SELECT timestamp, datahash, node_id, content_type, data"
|
||||
"SELECT timestamp, datahash, node_id, content_type, data, chain_hash"
|
||||
" FROM \"%s\" ORDER BY timestamp, datahash ASC", tbl);
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
if (sqlite3_prepare_v2(g_cc.db, sql, -1, &stmt, NULL) != SQLITE_OK) return 0;
|
||||
@@ -479,10 +479,12 @@ int chat_core_cursor_next(uint32_t cursor_id, uint8_t* buf, size_t buf_size,
|
||||
uint64_t nid= (uint64_t)sqlite3_column_int64(stmt, 2);
|
||||
const char* ct = (const char*)sqlite3_column_text(stmt, 3);
|
||||
int ct_len = sqlite3_column_bytes(stmt, 3);
|
||||
const uint8_t* data = (const uint8_t*)sqlite3_column_blob(stmt, 4);
|
||||
const uint8_t* dptr = (const uint8_t*)sqlite3_column_blob(stmt, 4);
|
||||
int dlen = sqlite3_column_bytes(stmt, 4);
|
||||
const uint8_t* ch_ptr = (const uint8_t*)sqlite3_column_blob(stmt, 5);
|
||||
int ch_len = sqlite3_column_bytes(stmt, 5);
|
||||
|
||||
size_t need = 8 + 8 + 8 + 1 + (size_t)ct_len + 4 + (size_t)dlen;
|
||||
size_t need = 8 + 8 + 8 + 1 + (size_t)ct_len + 4 + (size_t)dlen + 32;
|
||||
if (need > buf_size) return -1;
|
||||
|
||||
uint8_t* out = buf;
|
||||
@@ -493,7 +495,9 @@ int chat_core_cursor_next(uint32_t cursor_id, uint8_t* buf, size_t buf_size,
|
||||
if (ct_len) { memcpy(out, ct, (size_t)ct_len); out += ct_len; }
|
||||
uint32_t dl32 = (uint32_t)dlen;
|
||||
memcpy(out, &dl32, 4); out += 4;
|
||||
if (dlen) { memcpy(out, data, (size_t)dlen); out += dlen; }
|
||||
if (dlen) { memcpy(out, dptr, (size_t)dlen); out += dlen; }
|
||||
if (ch_ptr && ch_len >= 32) memcpy(out, ch_ptr, 32); else memset(out, 0, 32);
|
||||
out += 32;
|
||||
*out_len = (size_t)(out - buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -994,22 +998,40 @@ static void si_register(struct DB_SYNC_INSTANCE* si, const char* ch_id) {
|
||||
|
||||
static void on_db_sync_insert(struct DB_SYNC_INSTANCE* si, const char* data, size_t len, uint64_t author, void* arg) {
|
||||
const char* ch_id = (const char*)arg;
|
||||
uint64_t dh; compute_datahash((const uint8_t*)data, len, &dh);
|
||||
/* parse JSON: {"n":<uint64>,"ch":"<str>","ct":"<str>","d":"<str>"} */
|
||||
const char* p = data; const char* end = data + len; uint64_t jn = 0;
|
||||
{ /* "n" */
|
||||
const char* n = strstr(p, "\"n\":"); if (!n) return;
|
||||
n += 4; jn = strtoull(n, NULL, 0); p = n;
|
||||
}
|
||||
const char* jct = "text/plain"; size_t jct_len = 10;
|
||||
{ /* "ct" */
|
||||
const char* ct = strstr(p, "\"ct\":\""); if (ct) { ct += 6; const char* ce = strchr(ct, '"'); if (ce) { jct = ct; jct_len = (size_t)(ce - ct); p = ce; } }
|
||||
}
|
||||
const char* jd_start = NULL; size_t jd_len = 0;
|
||||
{ /* "d" */
|
||||
const char* d = strstr(p, "\"d\":\""); if (d) { d += 5; const char* de = d; while (de < end) { if (*de == '"' && (de == d || *(de - 1) != '\\')) break; de++; } if (de < end) { jd_start = d; jd_len = (size_t)(de - d); } }
|
||||
}
|
||||
if (!jd_start) return;
|
||||
|
||||
uint64_t dh; compute_datahash((const uint8_t*)jd_start, jd_len, &dh);
|
||||
uint64_t ts = get_time_us();
|
||||
char tbl[80]; msg_table_name(ch_id, tbl, sizeof(tbl));
|
||||
uint8_t prev_ch[32]; get_last_chain_hash(ch_id, prev_ch);
|
||||
uint8_t chain_h[32]; compute_chain_hash(prev_ch, (int64_t)ts, dh, chain_h);
|
||||
char sql[512]; snprintf(sql, sizeof(sql),
|
||||
"INSERT OR IGNORE INTO \"%s\" (node_id,content_type,data,timestamp,datahash,chain_hash,signature,is_outgoing,is_read,sync_flags)"
|
||||
" VALUES(?,?,?,?,?,?,?,?,?,?)", tbl);
|
||||
sqlite3_stmt* st=NULL;
|
||||
if (sqlite3_prepare_v2(g_cc.db,sql,-1,&st,NULL)!=SQLITE_OK) return;
|
||||
sqlite3_bind_int64(st,1,(sqlite3_int64)author);
|
||||
sqlite3_bind_text(st,2,"text/plain",-1,SQLITE_STATIC);
|
||||
sqlite3_bind_blob(st,3,data,(int)len,SQLITE_STATIC);
|
||||
sqlite3_bind_int64(st,1,(sqlite3_int64)jn);
|
||||
sqlite3_bind_text(st,2,jct,(int)jct_len,SQLITE_STATIC);
|
||||
sqlite3_bind_blob(st,3,jd_start,(int)jd_len,SQLITE_STATIC);
|
||||
sqlite3_bind_int64(st,4,(sqlite3_int64)ts);
|
||||
sqlite3_bind_int64(st,5,(sqlite3_int64)dh);
|
||||
{ static const uint8_t z32[32]={0}; sqlite3_bind_blob(st,6,z32,32,SQLITE_STATIC); }
|
||||
sqlite3_bind_blob(st,6,chain_h,32,SQLITE_STATIC);
|
||||
{ static const uint8_t z64[64]={0}; sqlite3_bind_blob(st,7,z64,64,SQLITE_STATIC); }
|
||||
sqlite3_bind_int(st,8,author==g_cc.my_node_id?1:0);
|
||||
sqlite3_bind_int(st,8,(uint64_t)jn==g_cc.my_node_id?1:0);
|
||||
sqlite3_bind_int(st,9,1); sqlite3_bind_int(st,10,0);
|
||||
int rc=sqlite3_step(st); sqlite3_finalize(st);
|
||||
if (rc==SQLITE_DONE) {
|
||||
|
||||
@@ -213,8 +213,9 @@ static void cs_handle_send_data(struct chat_sync* cs, uint64_t peer,
|
||||
ptr += ct_len; remain -= ct_len;
|
||||
if (remain < 4) break;
|
||||
uint32_t dlen; memcpy(&dlen, ptr, 4); ptr += 4; remain -= 4;
|
||||
if (remain < dlen) break;
|
||||
if (remain < dlen + 32) break;
|
||||
ptr += dlen; remain -= dlen;
|
||||
ptr += 32; remain -= 32; /* chain_hash */
|
||||
|
||||
size_t reclen = (size_t)(ptr - rec_start);
|
||||
chat_core_insert_record(ch_id, rec_start, reclen);
|
||||
@@ -949,6 +950,9 @@ static void cs_handle_channel_join(struct chat_sync* cs, uint64_t peer,
|
||||
ch = cs_find(cs, ch_id);
|
||||
}
|
||||
|
||||
{ uint8_t evt[65]; uint8_t cl=(uint8_t)strlen(ch_id); evt[0]=cl; memcpy(evt+1,ch_id,cl);
|
||||
gui_bridge_post(GUI_EVT_MEMBERS_CHANGED, evt, 1+cl); }
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: JOIN accepted node=0x%016llx ch=%s addrs=%d",
|
||||
CS_ID, (unsigned long long)node_id, ch_id, addr_cnt);
|
||||
}
|
||||
@@ -1000,6 +1004,26 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
|
||||
|
||||
cs_refresh_channels(cs);
|
||||
|
||||
/* initiate message sync with the inviter after join */
|
||||
for (int i = 0; i < cs->channel_count; i++) {
|
||||
struct channel_cache* ch2 = &cs->channels[i];
|
||||
if (strcmp(ch2->channel_id, ch_id) != 0) continue;
|
||||
int found = 0;
|
||||
for (int j = 0; j < ch2->peer_count; j++)
|
||||
if (ch2->peer_ids[j] == peer) { found = 1; break; }
|
||||
if (found) {
|
||||
ch2->synced = CS_SYNC_IN_PROGRESS;
|
||||
uint8_t msg[37]; msg[0] = CS_MSG_INIT_SYNC;
|
||||
chat_core_chain_hash_at(ch2->channel_id,
|
||||
ch2->msg_count > 0 ? ch2->msg_count - 1 : 0, ch2->last_chain_hash);
|
||||
memcpy(msg + 1, &ch2->msg_count, 4);
|
||||
memcpy(msg + 5, ch2->last_chain_hash, 32);
|
||||
cs_send(cs, ch2->channel_id, peer, msg, 37);
|
||||
member_sync_start(cs->inst, peer, ch2->channel_id, _on_member_sync_done, ch2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t evt[65]; uint8_t ch_id_len = (uint8_t)strlen(ch_id);
|
||||
evt[0] = ch_id_len; memcpy(evt + 1, ch_id, ch_id_len);
|
||||
gui_bridge_post(GUI_EVT_CHANNEL_UPDATED, evt, 1 + ch_id_len);
|
||||
|
||||
Reference in new issue
Block a user