Bound and safely serialize PM conversation snapshots
This commit is contained in:
1 parent
e562896d63
commit
d9eee4e520
1 file changed
+31
-8
+31
-8
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user