dm: прямой обмен сообщениями (DM) + soundtouch + архитектура звонков
- src/dm/: dm_core/dm_crypto/dm_mailbox — прямой обмен сообщениями (DM) - lib/soundtouch-master/: vendored SoundTouch (изменение темпа/высоты аудио) - doc/dm_arch.md, doc/chat_call_arch.md: архитектура DM и звонков - tests: test_dm.c, test_dm_e2e.c - chat: рефакторинг chat_* модулей, member_sync, invite_build - chatgui/chatgui-android: синхронизация с новым API чата - lib/u_async, debug_config, utun_instance: сопутствующие изменения
This commit is contained in:
1 parent
761f64cf76
commit
73fe99b33f
123 files changed
+14095
-1270
No files matched your search
@@ -4,6 +4,7 @@
|
||||
#include "headless_control.h"
|
||||
#include "../libutun_lite/utun_config_api.h"
|
||||
#include "../libutun_lite/invite_link_c.h"
|
||||
#include "../libutun_lite/instance_lite.h"
|
||||
#include "../../../src/chat/chat_setting.h"
|
||||
#include "../../../src/chat/chat_sync.h"
|
||||
#include "../../../lib/debug_config.h"
|
||||
@@ -315,7 +316,13 @@ static int handle_join(int fd, int id, const char* json) {
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "join: calling chat_sync_connect_from_invite...");
|
||||
chat_sync_connect_from_invite(d.channelId, d.nodeId, d.pubkey, addrs_buf, d.addrCount, addrs_len, d.password, d.join_key);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "join: no instance running — drop");
|
||||
send_response(fd, id, NULL, "instance not running");
|
||||
return 0;
|
||||
}
|
||||
chat_sync_connect_from_invite(inst, d.channelId, d.nodeId, d.pubkey, addrs_buf, d.addrCount, addrs_len, d.password, d.join_key);
|
||||
|
||||
char resp[512];
|
||||
snprintf(resp, sizeof(resp),
|
||||
@@ -331,7 +338,9 @@ static int handle_chat_setting(int fd, int id, const char* json) {
|
||||
send_response(fd, id, NULL, "missing name or value");
|
||||
return 0;
|
||||
}
|
||||
int rc = chat_setting_set(name, value);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst) { send_response(fd, id, NULL, "instance not running"); return 0; }
|
||||
int rc = chat_setting_set(inst, name, value);
|
||||
if (rc == -1) { send_response(fd, id, NULL, "unknown setting"); return 0; }
|
||||
if (rc == -2) { send_response(fd, id, NULL, "invalid value"); return 0; }
|
||||
printf("control: chat_setting %s=%s\n", name, value);
|
||||
|
||||
@@ -190,6 +190,7 @@ void utun_bridge_send_message(const char* channel_id, const char* text) {
|
||||
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen);
|
||||
if (!req) return;
|
||||
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->channel_id, channel_id, sizeof(req->channel_id) - 1);
|
||||
strncpy(req->content_type, "text/plain", sizeof(req->content_type) - 1);
|
||||
req->data = (uint8_t*)(req + 1);
|
||||
@@ -206,9 +207,11 @@ void utun_bridge_create_channel(const char* name, const char* channel_id) {
|
||||
if (!name || !name[0]) { bridge_log(BLEV_ERROR, "create_channel: empty name"); return; }
|
||||
struct UASYNC* ua = instance_lite_get_uasync();
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "create_channel: uasync not running"); return; }
|
||||
char* n = u_strdup(name);
|
||||
if (!n) { bridge_log(BLEV_ERROR, "create_channel: OOM"); return; }
|
||||
uasync_post(ua, chat_core_create_channel_auto_trampoline, n);
|
||||
struct chat_create_auto_arg* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "create_channel: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->name, sizeof(req->name), "%s", name);
|
||||
uasync_post(ua, chat_core_create_channel_auto_trampoline, req);
|
||||
}
|
||||
|
||||
void utun_bridge_connect_node(const char* address, int port, const char* pubkey_hex) {
|
||||
@@ -235,7 +238,13 @@ void utun_bridge_join_channel(uint64_t channel_id, uint64_t node_id,
|
||||
utun_bridge_event(6, "{\"node_id\":0,\"result\":-7}"); /* CHAT_EVT_CONNECT_RESULT */
|
||||
return;
|
||||
}
|
||||
chat_sync_connect_from_invite(channel_id, real_node_id, pubkey_bin, addrs_data, addr_count, addrs_data_len, NULL, join_key);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst) {
|
||||
bridge_log(BLEV_ERROR, "join: instance not running");
|
||||
utun_bridge_event(6, "{\"node_id\":0,\"result\":-7}"); /* CHAT_EVT_CONNECT_RESULT */
|
||||
return;
|
||||
}
|
||||
chat_sync_connect_from_invite(inst, channel_id, real_node_id, pubkey_bin, addrs_data, addr_count, addrs_data_len, NULL, join_key);
|
||||
}
|
||||
|
||||
void utun_bridge_request_invite_candidates(const char* channel_id) {
|
||||
@@ -245,10 +254,12 @@ void utun_bridge_request_invite_candidates(const char* channel_id) {
|
||||
}
|
||||
struct UASYNC* ua = instance_lite_get_uasync();
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "request_invite_candidates: uasync not running"); return; }
|
||||
char* cid = u_strdup(channel_id);
|
||||
if (!cid) { bridge_log(BLEV_ERROR, "request_invite_candidates: OOM"); return; }
|
||||
struct chat_invite_cand_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "request_invite_candidates: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->ch_id, sizeof(req->ch_id), "%s", channel_id);
|
||||
bridge_log(BLEV_INFO, "request_invite_candidates ch=%s", channel_id);
|
||||
uasync_post(ua, chat_invite_candidates_trampoline, cid);
|
||||
uasync_post(ua, chat_invite_candidates_trampoline, req);
|
||||
}
|
||||
|
||||
void utun_bridge_request_invite_link(const char* channel_id, uint64_t target_node_id) {
|
||||
@@ -260,6 +271,7 @@ void utun_bridge_request_invite_link(const char* channel_id, uint64_t target_nod
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "request_invite_link: uasync not running"); return; }
|
||||
struct chat_invite_build_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "request_invite_link: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->ch_id, channel_id, sizeof(req->ch_id) - 1);
|
||||
req->target_node_id = target_node_id;
|
||||
bridge_log(BLEV_INFO, "request_invite_link ch=%s target=0x%016llx",
|
||||
@@ -274,10 +286,12 @@ void utun_bridge_connect_channel(const char* channel_id) {
|
||||
}
|
||||
struct UASYNC* ua = instance_lite_get_uasync();
|
||||
if (!uasync_is_running(ua)) return;
|
||||
char* cid = u_strdup(channel_id);
|
||||
if (!cid) return;
|
||||
struct chat_create_auto_arg* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) return;
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->name, sizeof(req->name), "%s", channel_id);
|
||||
bridge_log(BLEV_INFO, "connect_channel ch=%s", channel_id);
|
||||
uasync_post(ua, chat_core_connect_channel_trampoline, cid);
|
||||
uasync_post(ua, chat_core_connect_channel_trampoline, req);
|
||||
}
|
||||
|
||||
void utun_bridge_connect_member_node(const char* channel_id, uint64_t node_id) {
|
||||
@@ -290,6 +304,7 @@ void utun_bridge_connect_member_node(const char* channel_id, uint64_t node_id) {
|
||||
if (!uasync_is_running(ua)) return;
|
||||
struct chat_connect_node_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "connect_member_node: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->ch_id, channel_id, sizeof(req->ch_id) - 1);
|
||||
req->node_id = node_id;
|
||||
bridge_log(BLEV_INFO, "connect_member_node ch=%s node=0x%016llx", channel_id, (unsigned long long)node_id);
|
||||
@@ -391,10 +406,11 @@ static void bridge_format_preview_body(const char* ct, const char* d, char* out,
|
||||
}
|
||||
|
||||
char* utun_bridge_get_channels_json(void) {
|
||||
sqlite3* db = chat_core_get_db();
|
||||
if (!chat_core_is_initialized() || !db) {
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
sqlite3* db = chat_core_get_db(inst);
|
||||
if (!chat_core_is_initialized(inst) || !db) {
|
||||
bridge_log(BLEV_WARN, "get_channels: not initialized db=%p initialized=%d",
|
||||
(void*)db, chat_core_is_initialized());
|
||||
(void*)db, chat_core_is_initialized(inst));
|
||||
return u_strdup("[]");
|
||||
}
|
||||
size_t cap = 4096, pos = 1;
|
||||
@@ -445,8 +461,7 @@ char* utun_bridge_get_channels_json(void) {
|
||||
}
|
||||
|
||||
int online = 0;
|
||||
uint64_t my_id = g_cc.my_node_id;
|
||||
struct UTUN_INSTANCE* inst = chat_core_get_inst();
|
||||
uint64_t my_id = inst->node_id;
|
||||
sqlite3_stmt* pc = NULL;
|
||||
snprintf(sql, sizeof(sql), "SELECT DISTINCT node_id FROM \"%s\"", tbl_peers);
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &pc, NULL) == SQLITE_OK) {
|
||||
@@ -480,9 +495,10 @@ char* utun_bridge_get_channels_json(void) {
|
||||
}
|
||||
|
||||
char* utun_bridge_get_messages_json(const char* channel_id, int limit) {
|
||||
sqlite3* db = chat_core_get_db();
|
||||
if (!chat_core_is_initialized() || !db || !channel_id || !channel_id[0]) return u_strdup("[]");
|
||||
uint64_t my_id = g_cc.my_node_id;
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
sqlite3* db = chat_core_get_db(inst);
|
||||
if (!chat_core_is_initialized(inst) || !db || !channel_id || !channel_id[0]) return u_strdup("[]");
|
||||
uint64_t my_id = inst->node_id;
|
||||
|
||||
char tbl_msg[80];
|
||||
msg_table_name(channel_id, tbl_msg, sizeof(tbl_msg));
|
||||
@@ -580,7 +596,8 @@ char* utun_bridge_get_messages_json(const char* channel_id, int limit) {
|
||||
}
|
||||
|
||||
uint64_t utun_bridge_get_my_node_id(void) {
|
||||
return chat_core_is_initialized() ? g_cc.my_node_id : 0;
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
return (inst && chat_core_is_initialized(inst)) ? inst->node_id : 0;
|
||||
}
|
||||
|
||||
void utun_bridge_set_debug_level(const char* category, const char* level) {
|
||||
@@ -594,11 +611,14 @@ void utun_bridge_set_debug_level(const char* category, const char* level) {
|
||||
}
|
||||
|
||||
void utun_bridge_chat_setting_set(const char* name, const char* value) {
|
||||
chat_core_set_setting(name, value);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst) { bridge_log(BLEV_ERROR, "chat_setting_set: instance not running"); return; }
|
||||
chat_core_set_setting(inst, name, value);
|
||||
}
|
||||
|
||||
int utun_bridge_chat_setting_get_int(const char* name, int def) {
|
||||
return chat_setting_get_int(name, def);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
return chat_setting_get_int(inst, name, def);
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────────────────────
|
||||
@@ -610,8 +630,9 @@ int utun_bridge_chat_setting_get_int(const char* name, int def) {
|
||||
#include <openssl/evp.h>
|
||||
|
||||
char* utun_bridge_get_channel_members_json(const char* channel_id) {
|
||||
sqlite3* db = chat_core_get_db();
|
||||
if (!chat_core_is_initialized() || !db || !channel_id || !channel_id[0]) return u_strdup("[]");
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
sqlite3* db = chat_core_get_db(inst);
|
||||
if (!chat_core_is_initialized(inst) || !db || !channel_id || !channel_id[0]) return u_strdup("[]");
|
||||
|
||||
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl));
|
||||
|
||||
@@ -644,7 +665,7 @@ char* utun_bridge_get_channel_members_json(const char* channel_id) {
|
||||
if (!json) { sqlite3_finalize(st); return u_strdup("[]"); }
|
||||
json[0] = '[';
|
||||
|
||||
uint64_t my_id = g_cc.my_node_id;
|
||||
uint64_t my_id = inst->node_id;
|
||||
int first = 1;
|
||||
|
||||
while (sqlite3_step(st) == SQLITE_ROW) {
|
||||
@@ -702,8 +723,9 @@ char* utun_bridge_get_channel_members_json(const char* channel_id) {
|
||||
}
|
||||
|
||||
char* utun_bridge_get_member_detail_json(const char* channel_id, uint64_t node_id) {
|
||||
sqlite3* db = chat_core_get_db();
|
||||
if (!chat_core_is_initialized() || !db || !channel_id || node_id == 0) return u_strdup("{}");
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
sqlite3* db = chat_core_get_db(inst);
|
||||
if (!chat_core_is_initialized(inst) || !db || !channel_id || node_id == 0) return u_strdup("{}");
|
||||
|
||||
char buf[8192];
|
||||
size_t pos = 0;
|
||||
@@ -774,8 +796,9 @@ char* utun_bridge_get_member_detail_json(const char* channel_id, uint64_t node_i
|
||||
}
|
||||
|
||||
void utun_bridge_set_member_nick(const char* channel_id, uint64_t node_id, const char* nick) {
|
||||
sqlite3* db = chat_core_get_db();
|
||||
if (!chat_core_is_initialized() || !db || !channel_id || node_id == 0) return;
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
sqlite3* db = chat_core_get_db(inst);
|
||||
if (!chat_core_is_initialized(inst) || !db || !channel_id || node_id == 0) return;
|
||||
|
||||
char peers_tbl[80]; peers_table_name(channel_id, peers_tbl, sizeof(peers_tbl));
|
||||
char sql[256];
|
||||
@@ -796,6 +819,7 @@ void utun_bridge_set_member_nick(const char* channel_id, uint64_t node_id, const
|
||||
}
|
||||
|
||||
struct member_tags_edit_req {
|
||||
struct UTUN_INSTANCE* inst;
|
||||
char ch_id[64];
|
||||
uint64_t node_id;
|
||||
int admin, supernode, moder, storage, verified, deleted;
|
||||
@@ -803,8 +827,8 @@ struct member_tags_edit_req {
|
||||
|
||||
static void member_tags_edit_trampoline(void* arg) {
|
||||
struct member_tags_edit_req* req = (struct member_tags_edit_req*)arg;
|
||||
if (!req) return;
|
||||
struct chat_member_tags* t = chat_member_tags_load(req->ch_id, req->node_id);
|
||||
if (!req || !req->inst) { u_free(arg); return; }
|
||||
struct chat_member_tags* t = chat_member_tags_load(req->inst, req->ch_id, req->node_id);
|
||||
if (!t) {
|
||||
bridge_log(BLEV_ERROR, "set_member_flags: tags_load failed ch=%s nid=0x%016llx",
|
||||
req->ch_id, (unsigned long long)req->node_id);
|
||||
@@ -817,7 +841,7 @@ static void member_tags_edit_trampoline(void* arg) {
|
||||
chat_member_tags_set(t, "storage", req->storage ? "yes" : "no");
|
||||
chat_member_tags_set(t, "verified", req->verified ? "yes" : "no");
|
||||
chat_member_tags_set(t, "deleted", req->deleted ? "yes" : "no");
|
||||
int rc = chat_member_tags_commit(t);
|
||||
int rc = chat_member_tags_commit(req->inst, t);
|
||||
bridge_log(rc == 0 ? BLEV_INFO : BLEV_ERROR,
|
||||
"set_member_flags ch=%s nid=0x%016llx admin=%d super=%d moder=%d storage=%d verified=%d deleted=%d rc=%d",
|
||||
req->ch_id, (unsigned long long)req->node_id, req->admin, req->supernode,
|
||||
@@ -827,8 +851,9 @@ static void member_tags_edit_trampoline(void* arg) {
|
||||
}
|
||||
|
||||
int utun_bridge_is_channel_owner(const char* channel_id) {
|
||||
sqlite3* db = chat_core_get_db();
|
||||
if (!chat_core_is_initialized() || !db || !channel_id || !channel_id[0]) return 0;
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
sqlite3* db = chat_core_get_db(inst);
|
||||
if (!chat_core_is_initialized(inst) || !db || !channel_id || !channel_id[0]) return 0;
|
||||
uint8_t priv[32];
|
||||
return topo_node_sqlite_channel_get_priv(db, channel_id, priv) == 0 ? 1 : 0;
|
||||
}
|
||||
@@ -841,6 +866,7 @@ void utun_bridge_set_member_flags(const char* channel_id, uint64_t node_id,
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "set_member_flags: uasync not running"); return; }
|
||||
struct member_tags_edit_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "set_member_flags: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->ch_id, channel_id, sizeof(req->ch_id) - 1);
|
||||
req->node_id = node_id;
|
||||
req->admin = admin; req->supernode = supernode; req->moder = moder;
|
||||
@@ -851,7 +877,7 @@ void utun_bridge_set_member_flags(const char* channel_id, uint64_t node_id,
|
||||
}
|
||||
|
||||
char* utun_bridge_get_member_links_json(uint64_t node_id) {
|
||||
struct UTUN_INSTANCE* inst = chat_core_get_inst();
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst || node_id == 0) return u_strdup("{}");
|
||||
|
||||
struct ETCP_CONN* conn = instance_find_conn(inst, node_id);
|
||||
@@ -916,6 +942,7 @@ void utun_bridge_transfer_admin(const char* channel_id, uint64_t node_id) {
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "transfer_admin: uasync not running"); return; }
|
||||
struct chat_transfer_admin_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "transfer_admin: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->ch_id, channel_id, sizeof(req->ch_id) - 1);
|
||||
req->target_node_id = node_id;
|
||||
uasync_post(ua, chat_core_transfer_admin_trampoline, req);
|
||||
@@ -932,6 +959,7 @@ void utun_bridge_delete_channel(const char* channel_id) {
|
||||
if (!uasync_is_running(ua)) { bridge_log(BLEV_ERROR, "delete_channel: uasync not running"); return; }
|
||||
struct chat_delete_channel_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) { bridge_log(BLEV_ERROR, "delete_channel: OOM"); return; }
|
||||
req->inst = instance_lite_get_instance();
|
||||
strncpy(req->ch_id, channel_id, sizeof(req->ch_id) - 1);
|
||||
uasync_post(ua, chat_core_delete_channel_trampoline, req);
|
||||
bridge_log(BLEV_INFO, "delete_channel queued ch=%s", channel_id);
|
||||
@@ -944,8 +972,8 @@ void utun_bridge_delete_channel(const char* channel_id) {
|
||||
#include "../../../lib/socket_compat.h"
|
||||
|
||||
char* utun_bridge_get_local_sockets_json(void) {
|
||||
if (!chat_core_is_initialized() || !g_cc.inst) return u_strdup("[]");
|
||||
struct UTUN_INSTANCE* inst = g_cc.inst;
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst || !chat_core_is_initialized(inst)) return u_strdup("[]");
|
||||
|
||||
size_t cap = 4096, pos = 1;
|
||||
char* json = u_malloc(cap);
|
||||
@@ -1049,14 +1077,15 @@ char* utun_bridge_get_local_sockets_json(void) {
|
||||
}
|
||||
|
||||
void utun_bridge_on_network_change(void) {
|
||||
if (!g_cc.inst) return;
|
||||
auto_socket_on_network_change(g_cc.inst);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst) return;
|
||||
auto_socket_on_network_change(inst);
|
||||
bridge_log(BLEV_DEBUG, "network change notified to auto_socket");
|
||||
}
|
||||
|
||||
static void bridge_set_active_trampoline(void* arg) {
|
||||
int active = (int)(intptr_t)arg;
|
||||
struct UTUN_INSTANCE* inst = chat_core_get_inst();
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (!inst) return;
|
||||
utun_set_client_activity(inst, active);
|
||||
standby_set_enabled(inst, !active);
|
||||
@@ -1181,6 +1210,7 @@ int utun_bridge_attachment_download(const char* channel_id, int64_t msg_id) {
|
||||
if (!uasync_is_running(ua)) return -1;
|
||||
struct attachment_dl_req* req = u_calloc(1, sizeof(*req));
|
||||
if (!req) return -1;
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id);
|
||||
req->msg_id = msg_id;
|
||||
bridge_log(BLEV_INFO, "attachment_download: ch=%s msg_id=%lld", channel_id, (long long)msg_id);
|
||||
@@ -1678,7 +1708,8 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeSetChatSetting(
|
||||
(void)thiz;
|
||||
const char* n = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
const char* v = (*env)->GetStringUTFChars(env, value, NULL);
|
||||
chat_core_set_setting(n, v);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
if (inst) chat_core_set_setting(inst, n, v);
|
||||
if (v) (*env)->ReleaseStringUTFChars(env, value, v);
|
||||
if (n) (*env)->ReleaseStringUTFChars(env, name, n);
|
||||
}
|
||||
@@ -1687,7 +1718,8 @@ JNIEXPORT jint JNICALL Java_com_utun_chat_data_NativeLib_nativeGetChatSettingInt
|
||||
JNIEnv* env, jobject thiz, jstring name, jint def) {
|
||||
(void)thiz;
|
||||
const char* n = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
int val = chat_setting_get_int(n, (int)def);
|
||||
struct UTUN_INSTANCE* inst = instance_lite_get_instance();
|
||||
int val = chat_setting_get_int(inst, n, (int)def);
|
||||
if (n) (*env)->ReleaseStringUTFChars(env, name, n);
|
||||
return (jint)val;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ int attachment_send(const char* channel_id, const char* src_file_path, const cha
|
||||
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1);
|
||||
if (!req) return -1;
|
||||
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id);
|
||||
snprintf(req->content_type, sizeof(req->content_type), "application/octet-stream");
|
||||
snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path);
|
||||
|
||||
@@ -158,7 +158,8 @@ static void cfg_get_val(const char* text, const char* key, char* out, size_t out
|
||||
|
||||
/* ── Chat event forward → Kotlin callback ── */
|
||||
|
||||
static void chat_event_forward(int type, const uint8_t* data, int len) {
|
||||
static void chat_event_forward(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int len) {
|
||||
(void)inst;
|
||||
if (g_event_handler) { g_event_handler(type, data, len); return; }
|
||||
IL_LOGE("[EVT_DIAG] chat_event_forward: g_event_handler is NULL! type=%d len=%d", type, len);
|
||||
}
|
||||
@@ -271,7 +272,6 @@ static void* instance_thread(void* arg) {
|
||||
}
|
||||
|
||||
IL_LOGI("[EVT_DIAG] thread: about to set chat_event handler, g_event_handler=%p", (void*)g_event_handler);
|
||||
chat_event_set_handler(chat_event_forward);
|
||||
ensure_keys(config);
|
||||
|
||||
g_inst = utun_instance_create_from_config(g_ua, config);
|
||||
@@ -285,6 +285,7 @@ static void* instance_thread(void* arg) {
|
||||
pthread_detach(pthread_self());
|
||||
return NULL;
|
||||
}
|
||||
chat_event_set_handler(g_inst, chat_event_forward);
|
||||
|
||||
IL_LOGI("instance created, node_id=0x%016llx", (unsigned long long)g_inst->node_id);
|
||||
|
||||
@@ -322,7 +323,7 @@ static void* instance_thread(void* arg) {
|
||||
}
|
||||
|
||||
/* sockets are now created — sync my addresses to DB */
|
||||
chat_core_sync_my_addresses();
|
||||
chat_core_sync_my_addresses(g_inst);
|
||||
fire_local_sockets_event();
|
||||
|
||||
/* Bind chat sync via etcp_router */
|
||||
@@ -333,7 +334,7 @@ static void* instance_thread(void* arg) {
|
||||
|
||||
/* Set my_name from config */
|
||||
if (g_inst->config->global.name[0]) {
|
||||
chat_core_update_my_name(g_inst->config->global.name);
|
||||
chat_core_update_my_name(g_inst, g_inst->config->global.name);
|
||||
IL_LOGI("my_name set to '%s'", g_inst->config->global.name);
|
||||
}
|
||||
|
||||
@@ -341,13 +342,13 @@ static void* instance_thread(void* arg) {
|
||||
|
||||
/* Notify GUI of current public key (initial generation or existing) */
|
||||
if (strlen(config->global.my_public_key_hex) == 64) {
|
||||
chat_event_post(CHAT_EVT_KEYS_GENERATED,
|
||||
chat_event_post(g_inst, CHAT_EVT_KEYS_GENERATED,
|
||||
(const uint8_t*)config->global.my_public_key_hex, 64);
|
||||
}
|
||||
|
||||
__atomic_store_n(&g_running, 1, __ATOMIC_RELEASE);
|
||||
uasync_mark_running(g_ua);
|
||||
chat_event_post(CHAT_EVT_SERVICE_STARTED, NULL, 0);
|
||||
chat_event_post(g_inst, CHAT_EVT_SERVICE_STARTED, NULL, 0);
|
||||
|
||||
while (!__atomic_load_n(&g_stop, __ATOMIC_ACQUIRE)) {
|
||||
uasync_poll(g_ua, -1);
|
||||
@@ -373,8 +374,6 @@ static void* instance_thread(void* arg) {
|
||||
if (!g_ua) { IL_LOGE("poll exit: uasync_create failed"); break; }
|
||||
standby_init(g_ua);
|
||||
|
||||
chat_event_set_handler(chat_event_forward);
|
||||
|
||||
char* cfg = (char*)__atomic_exchange_n(&g_restart_config, NULL, __ATOMIC_ACQUIRE);
|
||||
if (!cfg) { IL_LOGE("poll exit: restart_config is NULL"); break; }
|
||||
__atomic_store_n(&g_stop, 0, __ATOMIC_RELEASE);
|
||||
@@ -386,6 +385,7 @@ static void* instance_thread(void* arg) {
|
||||
|
||||
g_inst = utun_instance_create_from_config(g_ua, config);
|
||||
if (!g_inst) { IL_LOGE("poll exit: create_from_config failed"); break; }
|
||||
chat_event_set_handler(g_inst, chat_event_forward);
|
||||
|
||||
char db_file[512];
|
||||
snprintf(db_file, sizeof(db_file), "%s/chats.db", g_db_path);
|
||||
@@ -399,17 +399,17 @@ static void* instance_thread(void* arg) {
|
||||
} else { IL_LOGE("poll exit: SQLite open failed rc=%d", rc); break; }
|
||||
|
||||
if (utun_instance_init(g_inst) != 0) { IL_LOGE("poll exit: utun_instance_init failed"); break; }
|
||||
chat_core_sync_my_addresses();
|
||||
chat_core_sync_my_addresses(g_inst);
|
||||
fire_local_sockets_event();
|
||||
if (g_inst->config->global.name[0]) chat_core_update_my_name(g_inst->config->global.name);
|
||||
if (g_inst->config->global.name[0]) chat_core_update_my_name(g_inst, g_inst->config->global.name);
|
||||
etcp_router_bind(g_inst, ETCP_RT_ID_CHAT_SYNC, NULL);
|
||||
utun_add_nodeinfo_cbk(g_inst, nodeinfo_event_cb, NULL);
|
||||
etcp_add_link_status_cbk(g_inst, on_link_status_changed, NULL);
|
||||
chat_event_post(CHAT_EVT_KEYS_GENERATED, (const uint8_t*)config->global.my_public_key_hex, 64);
|
||||
utun_add_nodeinfo_cbk(g_inst, nodeinfo_event_cb, NULL);
|
||||
etcp_add_link_status_cbk(g_inst, on_link_status_changed, NULL);
|
||||
chat_event_post(g_inst, CHAT_EVT_KEYS_GENERATED, (const uint8_t*)config->global.my_public_key_hex, 64);
|
||||
|
||||
__atomic_store_n(&g_running, 1, __ATOMIC_RELEASE);
|
||||
uasync_mark_running(g_ua);
|
||||
chat_event_post(CHAT_EVT_SERVICE_STARTED, NULL, 0);
|
||||
chat_event_post(g_inst, CHAT_EVT_SERVICE_STARTED, NULL, 0);
|
||||
|
||||
IL_LOGI("poll exit: restart done, entering new poll loop");
|
||||
while (!__atomic_load_n(&g_stop, __ATOMIC_ACQUIRE)) uasync_poll(g_ua, -1);
|
||||
@@ -420,6 +420,7 @@ static void* instance_thread(void* arg) {
|
||||
if (my_gen == g_generation) {
|
||||
__atomic_store_n(&g_running, 0, __ATOMIC_RELEASE);
|
||||
if (g_inst) {
|
||||
chat_event_post(g_inst, CHAT_EVT_SERVICE_STOPPED, NULL, 0);
|
||||
utun_instance_destroy(g_inst);
|
||||
g_inst = NULL;
|
||||
}
|
||||
@@ -431,7 +432,6 @@ static void* instance_thread(void* arg) {
|
||||
char* stale_cfg = (char*)__atomic_exchange_n(&g_restart_config, NULL, __ATOMIC_ACQUIRE);
|
||||
u_free(stale_cfg);
|
||||
u_report_unfreed_blocks();
|
||||
chat_event_post(CHAT_EVT_SERVICE_STOPPED, NULL, 0);
|
||||
IL_LOGI("cleanup complete (gen=%d)", my_gen);
|
||||
} else {
|
||||
IL_LOGI("cleanup skipped — thread gen=%d but current gen=%d (stale thread)", my_gen, g_generation);
|
||||
@@ -662,16 +662,19 @@ int instance_lite_is_responsive(void) {
|
||||
|
||||
void instance_lite_collect_conn_list(void) {
|
||||
struct UASYNC* ua = (struct UASYNC*)__atomic_load_n(&g_ua, __ATOMIC_ACQUIRE);
|
||||
if (!ua) return;
|
||||
uasync_post(ua, chat_core_collect_conn_list_trampoline, NULL);
|
||||
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)__atomic_load_n(&g_inst, __ATOMIC_ACQUIRE);
|
||||
if (!ua || !inst) return;
|
||||
uasync_post(ua, chat_core_collect_conn_list_trampoline, inst);
|
||||
}
|
||||
|
||||
void instance_lite_collect_conn_metrics(uint64_t peer_node_id) {
|
||||
struct UASYNC* ua = (struct UASYNC*)__atomic_load_n(&g_ua, __ATOMIC_ACQUIRE);
|
||||
if (!ua) return;
|
||||
uint64_t* arg = (uint64_t*)u_malloc(sizeof(uint64_t));
|
||||
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)__atomic_load_n(&g_inst, __ATOMIC_ACQUIRE);
|
||||
if (!ua || !inst) return;
|
||||
struct chat_node_arg* arg = (struct chat_node_arg*)u_malloc(sizeof(struct chat_node_arg));
|
||||
if (!arg) return;
|
||||
*arg = peer_node_id;
|
||||
arg->inst = inst;
|
||||
arg->node_id = peer_node_id;
|
||||
uasync_post(ua, chat_core_collect_conn_metrics_trampoline, arg);
|
||||
}
|
||||
|
||||
@@ -684,6 +687,10 @@ struct UASYNC* instance_lite_get_uasync(void) {
|
||||
return (struct UASYNC*)__atomic_load_n(&g_ua, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
struct UTUN_INSTANCE* instance_lite_get_instance(void) {
|
||||
return (struct UTUN_INSTANCE*)__atomic_load_n(&g_inst, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
static void regenerate_trampoline(void* arg) {
|
||||
(void)arg;
|
||||
if (!g_inst || !g_inst->config) { IL_LOGE("regenerate_keys: instance not running"); return; }
|
||||
@@ -698,7 +705,7 @@ static void regenerate_trampoline(void* arg) {
|
||||
g_inst->node_id = sc_derive_node_id_from_pubkey(pk_bin);
|
||||
sc_init_local_keys(&g_inst->my_keys, g_generated_pub, g_generated_priv);
|
||||
IL_LOGI("keys regenerated, node_id=0x%016llx", (unsigned long long)g_inst->node_id);
|
||||
chat_event_post(CHAT_EVT_KEYS_GENERATED, (const uint8_t*)g_generated_pub, 64);
|
||||
chat_event_post(g_inst, CHAT_EVT_KEYS_GENERATED, (const uint8_t*)g_generated_pub, 64);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,5 +719,8 @@ void instance_lite_regenerate_keys(void) {
|
||||
void instance_lite_set_event_handler(instance_lite_event_fn handler) {
|
||||
IL_LOGI("[EVT_DIAG] instance_lite_set_event_handler handler=%p g_running=%d", (void*)handler, g_running);
|
||||
g_event_handler = handler;
|
||||
if (__atomic_load_n(&g_running, __ATOMIC_ACQUIRE)) chat_event_set_handler(chat_event_forward);
|
||||
if (__atomic_load_n(&g_running, __ATOMIC_ACQUIRE)) {
|
||||
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)__atomic_load_n(&g_inst, __ATOMIC_ACQUIRE);
|
||||
if (inst) chat_event_set_handler(inst, chat_event_forward);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct UASYNC;
|
||||
struct UTUN_INSTANCE;
|
||||
|
||||
/* Start full uTun stack from INI config text.
|
||||
* Creates a pthread for uasync event loop.
|
||||
@@ -32,6 +33,9 @@ int instance_lite_is_running(void);
|
||||
/* Get current uasync handle (NULL if not running). */
|
||||
struct UASYNC* instance_lite_get_uasync(void);
|
||||
|
||||
/* Get current UTUN_INSTANCE handle (NULL if not running). */
|
||||
struct UTUN_INSTANCE* instance_lite_get_instance(void);
|
||||
|
||||
/* Set Kotlin callback for chat events (CONNECT_RESULT, MSG_RECEIVED, ...) */
|
||||
typedef void (*instance_lite_event_fn)(int type, const uint8_t* data, int len);
|
||||
void instance_lite_set_event_handler(instance_lite_event_fn handler);
|
||||
|
||||
@@ -74,6 +74,7 @@ int photo_send(const char* channel_id, const char* src_file_path, const char* db
|
||||
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1);
|
||||
if (!req) return -1;
|
||||
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id);
|
||||
snprintf(req->content_type, sizeof(req->content_type), "%s", content_type);
|
||||
snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path);
|
||||
|
||||
@@ -38,6 +38,7 @@ struct standby_wait_entry {
|
||||
};
|
||||
|
||||
static struct UASYNC* g_ua = NULL;
|
||||
static struct UTUN_INSTANCE* g_inst = NULL; /* для чтения chat_setting (per-instance) */
|
||||
static int g_enabled = 0;
|
||||
static int g_phase = PHASE_ACTIVE;
|
||||
static uint64_t g_phase_start_tb = 0; /* начало текущей фазы */
|
||||
@@ -59,15 +60,15 @@ static uint32_t g_cnt_net_events = 0;
|
||||
static uint32_t g_cnt_net_ignored = 0;
|
||||
|
||||
static int standby_active_sec(void) {
|
||||
return chat_setting_get_int("standby_active_sec", 2);
|
||||
return chat_setting_get_int(g_inst, "standby_active_sec", 2);
|
||||
}
|
||||
|
||||
static int standby_sleep_sec(void) {
|
||||
return chat_setting_get_int("standby_sleep_sec", 60);
|
||||
return chat_setting_get_int(g_inst, "standby_sleep_sec", 60);
|
||||
}
|
||||
|
||||
static int standby_min_sleep_sec(void) {
|
||||
int m = chat_setting_get_int("standby_min_sleep_sec", 15);
|
||||
int m = chat_setting_get_int(g_inst, "standby_min_sleep_sec", 15);
|
||||
if (m < 0) m = 0;
|
||||
int s = standby_sleep_sec();
|
||||
if (m > s) m = s;
|
||||
@@ -195,6 +196,7 @@ static void standby_wait_timer_cb(void* arg) {
|
||||
|
||||
void standby_init(struct UASYNC* ua) {
|
||||
g_ua = ua;
|
||||
g_inst = NULL;
|
||||
g_enabled = 0;
|
||||
g_phase = PHASE_ACTIVE;
|
||||
g_phase_timer = NULL;
|
||||
@@ -225,6 +227,7 @@ void standby_deinit(void) {
|
||||
}
|
||||
g_enabled = 0;
|
||||
g_ua = NULL;
|
||||
g_inst = NULL;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "standby: deinit (wakes_timer=%u wakes_early=%u sleeps=%u net=%u ignored=%u)",
|
||||
g_cnt_wakes_timer, g_cnt_wakes_early, g_cnt_sleeps, g_cnt_net_events, g_cnt_net_ignored);
|
||||
}
|
||||
@@ -234,6 +237,7 @@ void standby_set_enabled(struct UTUN_INSTANCE* inst, int enabled) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "standby: set_enabled(%d) but not initialized", enabled);
|
||||
return;
|
||||
}
|
||||
if (inst) g_inst = inst;
|
||||
if (g_enabled == enabled) return;
|
||||
|
||||
if (enabled) {
|
||||
|
||||
@@ -63,6 +63,7 @@ int video_send(const char* channel_id, const char* src_file_path, const char* db
|
||||
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1);
|
||||
if (!req) return -1;
|
||||
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id);
|
||||
snprintf(req->content_type, sizeof(req->content_type), "video/mp4");
|
||||
snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path);
|
||||
|
||||
@@ -383,6 +383,7 @@ int voice_recorder_stop(int* out_duration_ms) {
|
||||
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + total_data_len + 1);
|
||||
if (!req) { voice_cleanup_locked(g_rec); pthread_mutex_unlock(&g_rec->mtx); pthread_mutex_unlock(&g_init_mtx); return -1; }
|
||||
|
||||
req->inst = instance_lite_get_instance();
|
||||
snprintf(req->channel_id, sizeof(req->channel_id), "%s", g_rec->channel_id);
|
||||
snprintf(req->content_type, sizeof(req->content_type), "audio/opus");
|
||||
snprintf(req->media_src, sizeof(req->media_src), "%s", temp_path);
|
||||
|
||||
Reference in new issue
Block a user