|
|
|
|
@ -852,12 +852,13 @@ static void json_escape(const char* src, char* dst, size_t dst_sz) {
|
|
|
|
|
int dm_list_conversations_json(struct UTUN_INSTANCE* inst, char* buf, size_t buf_size, size_t* out_len) { |
|
|
|
|
struct dm_state* dm = dm_of(inst); |
|
|
|
|
if (!buf || !out_len || !dm || !dm->db) return -1; |
|
|
|
|
int off = 0; |
|
|
|
|
off += snprintf(buf + off, buf_size - (size_t)off, "["); |
|
|
|
|
*out_len = 0; |
|
|
|
|
struct strbuf json = strbuf_new(); |
|
|
|
|
int failed = strbuf_addf(&json, "[") < 0; |
|
|
|
|
sqlite3_stmt* st = NULL; |
|
|
|
|
if (sqlite3_prepare_v2(dm->db, |
|
|
|
|
"SELECT conv_id, peer_node_id, COALESCE(peer_name,''), last_ts, last_out_seq, last_in_seq" |
|
|
|
|
" FROM dm_conversations ORDER BY last_ts DESC", |
|
|
|
|
" FROM dm_conversations ORDER BY last_ts DESC LIMIT 200", |
|
|
|
|
-1, &st, NULL) == SQLITE_OK) { |
|
|
|
|
int first = 1; |
|
|
|
|
while (sqlite3_step(st) == SQLITE_ROW) { |
|
|
|
|
@ -875,18 +876,26 @@ int dm_list_conversations_json(struct UTUN_INSTANCE* inst, char* buf, size_t buf
|
|
|
|
|
} |
|
|
|
|
char esc_name[512]; |
|
|
|
|
json_escape(name ? name : "", esc_name, sizeof(esc_name)); |
|
|
|
|
off += snprintf(buf + off, buf_size - (size_t)off, |
|
|
|
|
if (strbuf_addf(&json, |
|
|
|
|
"%s{\"conv_id\":\"%s\",\"peer_node_id\":%llu,\"peer_name\":\"%s\"," |
|
|
|
|
"\"last_ts\":%llu,\"out_seq\":%llu,\"in_seq\":%llu}", |
|
|
|
|
first ? "" : ",", conv_id, (unsigned long long)peer, |
|
|
|
|
esc_name, (unsigned long long)last_ts, |
|
|
|
|
(unsigned long long)out_seq, (unsigned long long)in_seq); |
|
|
|
|
(unsigned long long)out_seq, (unsigned long long)in_seq) < 0) { failed = 1; break; } |
|
|
|
|
first = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (sqlite3_errcode(dm->db) != SQLITE_DONE && sqlite3_errcode(dm->db) != SQLITE_OK) failed = 1; |
|
|
|
|
} else failed = 1; |
|
|
|
|
if (st) sqlite3_finalize(st); |
|
|
|
|
off += snprintf(buf + off, buf_size - (size_t)off, "]"); |
|
|
|
|
*out_len = (size_t)off; |
|
|
|
|
if (strbuf_addf(&json, "]") < 0) failed = 1; |
|
|
|
|
if (failed || json.len >= buf_size) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: conversations snapshot failed bytes=%zu capacity=%zu sql=%s", DM_ID, |
|
|
|
|
json.len, buf_size, sqlite3_errmsg(dm->db)); |
|
|
|
|
strbuf_free(&json); return -1; |
|
|
|
|
} |
|
|
|
|
memcpy(buf, strbuf_str(&json), json.len + 1); |
|
|
|
|
*out_len = json.len; |
|
|
|
|
strbuf_free(&json); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1017,3 +1026,17 @@ void dm_messages_trampoline(void* arg) {
|
|
|
|
|
chat_event_post(inst, CHAT_EVT_DM_MESSAGES, evt, (int)(1 + cl + len)); |
|
|
|
|
u_free(evt); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void dm_conversations_trampoline(void* arg) { |
|
|
|
|
struct dm_conversations_req* req = arg; |
|
|
|
|
if (!req) return; |
|
|
|
|
struct UTUN_INSTANCE* inst = req->inst; |
|
|
|
|
u_free(req); |
|
|
|
|
if (!dm_of(inst)) { DEBUG_WARN(DEBUG_CATEGORY_DM, "%s: conversations snapshot after stop", DM_ID); return; } |
|
|
|
|
size_t cap = 256 * 1024, len = 0; |
|
|
|
|
char* json = u_malloc(cap); |
|
|
|
|
if (!json) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: conversations allocation failed", DM_ID); return; } |
|
|
|
|
if (!dm_list_conversations_json(inst, json, cap, &len)) |
|
|
|
|
chat_event_post(inst, CHAT_EVT_DM_CONVERSATIONS, (const uint8_t*)json, (int)len); |
|
|
|
|
u_free(json); |
|
|
|
|
} |
|
|
|
|
|