stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
This commit is contained in:
1 parent
a3783b5f55
commit
38c9f229bc
1272 files changed
+968388
-1
No files matched your search
@@ -0,0 +1,296 @@
|
||||
#include "gui_bridge.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMetaObject>
|
||||
#include <QByteArray>
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
#include "../../../lib/u_async.h"
|
||||
#include "../../../lib/mem.h"
|
||||
#include "../../../lib/debug_config.h"
|
||||
#include "../../../src/routing_layer/topo_node.h"
|
||||
#include "../../../src/routing_layer/topo_group.h"
|
||||
}
|
||||
|
||||
/* ── Внутренний объект-приёмник в GUI-потоке ── */
|
||||
|
||||
class GuiBridgeReceiver : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
void* ua = nullptr;
|
||||
|
||||
GuiBridgeReceiver(QObject* parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE void processPost(int eventType, QByteArray data);
|
||||
};
|
||||
|
||||
static GuiBridgeReceiver* g_receiver = nullptr;
|
||||
static gui_connect_result_fn g_connect_result_cb = nullptr;
|
||||
static gui_msg_received_fn g_msg_received_cb = nullptr;
|
||||
static gui_channel_updated_fn g_channel_updated_cb = nullptr;
|
||||
static gui_members_changed_fn g_members_changed_cb = nullptr;
|
||||
static gui_my_node_id_fn g_my_node_id_cb = nullptr;
|
||||
static gui_auto_connect_status_fn g_auto_connect_status_cb = nullptr;
|
||||
static gui_channel_peers_online_fn g_channel_peers_online_cb = nullptr;
|
||||
static gui_db_ready_fn g_db_ready_cb = nullptr;
|
||||
static gui_status_refresh_fn g_status_refresh_cb = nullptr;
|
||||
static gui_attachment_downloaded_fn g_attachment_downloaded_cb = nullptr;
|
||||
static gui_download_progress_fn g_download_progress_cb = nullptr;
|
||||
static gui_nodeinfo_update_fn g_nodeinfo_update_cb = nullptr;
|
||||
static gui_invite_received_fn g_invite_received_cb = nullptr;
|
||||
static struct UASYNC* g_ua = nullptr;
|
||||
|
||||
/* ── GuiBridgeReceiver implementation ── */
|
||||
|
||||
void GuiBridgeReceiver::processPost(int eventType, QByteArray data) {
|
||||
const uint8_t* d = (const uint8_t*)data.constData();
|
||||
int dlen = data.size();
|
||||
|
||||
switch (eventType) {
|
||||
case GUI_EVT_MSG_RECEIVED:
|
||||
if (dlen >= 2) {
|
||||
uint8_t chLen = d[0];
|
||||
if (dlen >= 1 + chLen + 8) {
|
||||
uint64_t author = 0;
|
||||
memcpy(&author, d + 1 + chLen, 8);
|
||||
QString chId = QString::fromUtf8((const char*)d + 1, chLen);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: MSG_RECEIVED ch=%s author=%llu",
|
||||
qPrintable(chId), (unsigned long long)author);
|
||||
if (g_msg_received_cb) g_msg_received_cb((const char*)d + 1, chLen, author);
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: MSG_RECEIVED invalid data length %d", dlen);
|
||||
}
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: MSG_RECEIVED data too short %d", dlen);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_CONNECT_RESULT:
|
||||
if (dlen >= 20) {
|
||||
uint64_t nodeId, channelId; int result;
|
||||
memcpy(&nodeId, d, 8); memcpy(&result, d + 8, 4); memcpy(&channelId, d + 12, 8);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "gui_bridge: CONNECT_RESULT node=0x%016llx ch=%llu result=%d",
|
||||
(unsigned long long)nodeId, (unsigned long long)channelId, result);
|
||||
if (g_connect_result_cb) g_connect_result_cb(nodeId, channelId, result);
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: CONNECT_RESULT data too short %d", dlen);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_NEW_PEER:
|
||||
if (dlen >= 8) {
|
||||
uint64_t nodeId; memcpy(&nodeId, d, 8);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "gui_bridge: NEW_PEER node=0x%016llx", (unsigned long long)nodeId);
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: NEW_PEER data too short %d", dlen);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_CHANNEL_UPDATED:
|
||||
if (dlen >= 2) {
|
||||
uint8_t chLen = d[0];
|
||||
if (dlen >= 1 + chLen) {
|
||||
QString chId = QString::fromUtf8((const char*)d + 1, chLen);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: CHANNEL_UPDATED ch=%s", qPrintable(chId));
|
||||
if (g_channel_updated_cb) g_channel_updated_cb((const char*)d + 1, chLen);
|
||||
}
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: CHANNEL_UPDATED data too short %d", dlen);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_MEMBERS_CHANGED:
|
||||
if (dlen >= 2) {
|
||||
uint8_t chLen = d[0];
|
||||
if (dlen >= 1 + chLen) {
|
||||
QString chId = QString::fromUtf8((const char*)d + 1, chLen);
|
||||
if (g_members_changed_cb) g_members_changed_cb((const char*)d + 1, chLen);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_MY_NODE_ID:
|
||||
if (dlen >= 8) {
|
||||
uint64_t nid; memcpy(&nid, d, 8);
|
||||
if (g_my_node_id_cb) g_my_node_id_cb(nid);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_AUTO_CONNECT_STATUS:
|
||||
if (dlen >= 7) {
|
||||
uint8_t status = d[0];
|
||||
uint16_t total_tried; memcpy(&total_tried, d + 1, 2);
|
||||
uint16_t node_count; memcpy(&node_count, d + 3, 2);
|
||||
uint16_t connected; memcpy(&connected, d + 5, 2);
|
||||
const char* st_str = status == 0 ? "in_progress" : status == 1 ? "done" : "stopped";
|
||||
if (status != 0) DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "gui_bridge: AUTO_CONNECT %s tried=%u/%u connected=%u", st_str, total_tried, node_count, connected);
|
||||
if (g_auto_connect_status_cb) g_auto_connect_status_cb(status, total_tried, node_count, connected);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_CHANNEL_PEERS_ONLINE:
|
||||
if (dlen >= 3) {
|
||||
uint8_t chLen = d[0];
|
||||
if (dlen >= 3 + chLen) {
|
||||
uint16_t online; memcpy(&online, d + 1 + chLen, 2);
|
||||
static char lastChId[256] = {0};
|
||||
static uint16_t lastOnline = 0xFFFF;
|
||||
if (chLen != (uint8_t)strlen(lastChId) || memcmp(lastChId, d + 1, chLen) != 0 || online != lastOnline) {
|
||||
memcpy(lastChId, d + 1, chLen); lastChId[chLen] = '\0';
|
||||
lastOnline = online;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: CHANNEL_PEERS_ONLINE ch=%.*s online=%u", chLen, (const char*)d + 1, online);
|
||||
}
|
||||
if (g_channel_peers_online_cb) g_channel_peers_online_cb((const char*)d + 1, chLen, online);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_DB_READY:
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "gui_bridge: DB_READY (chat DB tables created)");
|
||||
if (g_db_ready_cb) g_db_ready_cb();
|
||||
break;
|
||||
case GUI_EVT_STATUS_REFRESH:
|
||||
if (g_status_refresh_cb) g_status_refresh_cb((const char*)d, dlen);
|
||||
break;
|
||||
case GUI_EVT_NODE_CHANGED:
|
||||
if (dlen >= 8) {
|
||||
uint64_t nodeId; memcpy(&nodeId, d, 8);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "gui_bridge: NODE_CHANGED node=0x%016llx — pubkey changed, connection closed", (unsigned long long)nodeId);
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: NODE_CHANGED data too short %d", dlen);
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_ATTACHMENT_DOWNLOADED:
|
||||
if (dlen >= 2) {
|
||||
uint8_t chLen = d[0];
|
||||
if (dlen >= 1 + chLen + 8) {
|
||||
int64_t msgId = 0; memcpy(&msgId, d + 1 + chLen, 8);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "gui_bridge: ATTACHMENT_DOWNLOADED ch=%.*s msgId=%lld", chLen, (const char*)d + 1, (long long)msgId);
|
||||
if (g_attachment_downloaded_cb) g_attachment_downloaded_cb((const char*)d + 1, chLen, msgId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_DOWNLOAD_PROGRESS:
|
||||
if (dlen >= 2) {
|
||||
uint8_t chLen = d[0];
|
||||
if (dlen >= 1 + chLen + 16) {
|
||||
int64_t msgId = 0; memcpy(&msgId, d + 1 + chLen, 8);
|
||||
int32_t bd = 0, nb = 0; memcpy(&bd, d + 1 + chLen + 8, 4); memcpy(&nb, d + 1 + chLen + 12, 4);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "gui_bridge: DOWNLOAD_PROGRESS ch=%.*s msgId=%lld %d/%d", chLen, (const char*)d + 1, (long long)msgId, bd, nb);
|
||||
if (g_download_progress_cb) g_download_progress_cb((const char*)d + 1, chLen, msgId, bd, nb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GUI_EVT_NODEINFO_UPDATE:
|
||||
if (g_nodeinfo_update_cb) g_nodeinfo_update_cb(d, dlen);
|
||||
break;
|
||||
case 18: /* CHAT_EVT_INVITE_RECEIVED */
|
||||
if (g_invite_received_cb) g_invite_received_cb(d, dlen);
|
||||
break;
|
||||
default:
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge: unknown event type %d", eventType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── C API ── */
|
||||
|
||||
extern "C" {
|
||||
|
||||
void gui_bridge_init(void) {
|
||||
g_receiver = new GuiBridgeReceiver();
|
||||
g_receiver->ua = g_ua;
|
||||
}
|
||||
|
||||
void gui_bridge_set_uasync(struct UASYNC* ua) {
|
||||
g_ua = ua;
|
||||
if (g_receiver) g_receiver->ua = ua;
|
||||
}
|
||||
|
||||
void gui_bridge_post(int event_type, const uint8_t* data, int data_len) {
|
||||
if (!g_receiver) { DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge_post: g_receiver=NULL, dropping event %d", event_type); return; }
|
||||
|
||||
QByteArray d;
|
||||
if (data_len > 0) d = QByteArray((const char*)data, data_len);
|
||||
|
||||
QMetaObject::invokeMethod(g_receiver, "processPost",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int, event_type),
|
||||
Q_ARG(QByteArray, d));
|
||||
}
|
||||
|
||||
void gui_bridge_post_uasync_fn(void (*fn)(void*), void* arg) {
|
||||
if (!g_ua) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "gui_bridge_post_uasync_fn: g_ua=NULL, post dropped");
|
||||
return;
|
||||
}
|
||||
if (!fn) return;
|
||||
uasync_post(g_ua, fn, arg);
|
||||
}
|
||||
|
||||
int gui_bridge_is_uasync_ready(void) {
|
||||
return g_ua != NULL ? 1 : 0;
|
||||
}
|
||||
|
||||
void gui_bridge_set_connect_result_cb(gui_connect_result_fn cb) {
|
||||
g_connect_result_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_msg_received_cb(gui_msg_received_fn cb) {
|
||||
g_msg_received_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_channel_updated_cb(gui_channel_updated_fn cb) {
|
||||
g_channel_updated_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_members_changed_cb(gui_members_changed_fn cb) {
|
||||
g_members_changed_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_my_node_id_cb(gui_my_node_id_fn cb) {
|
||||
g_my_node_id_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_auto_connect_status_cb(gui_auto_connect_status_fn cb) {
|
||||
g_auto_connect_status_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_channel_peers_online_cb(gui_channel_peers_online_fn cb) {
|
||||
g_channel_peers_online_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_db_ready_cb(gui_db_ready_fn cb) {
|
||||
g_db_ready_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_status_refresh_cb(gui_status_refresh_fn cb) {
|
||||
g_status_refresh_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_attachment_downloaded_cb(gui_attachment_downloaded_fn cb) {
|
||||
g_attachment_downloaded_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_download_progress_cb(gui_download_progress_fn cb) {
|
||||
g_download_progress_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_nodeinfo_update_cb(gui_nodeinfo_update_fn cb) {
|
||||
g_nodeinfo_update_cb = cb;
|
||||
}
|
||||
|
||||
void gui_bridge_set_invite_received_cb(gui_invite_received_fn cb) {
|
||||
g_invite_received_cb = cb;
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
/* ── uTun nodeinfo callback (called from uasync thread) ── */
|
||||
|
||||
extern "C" void gui_nodeinfo_cb_impl(struct TOPO_GROUP* group, struct TOPO_GROUP_NODE* nq, void* arg) {
|
||||
(void)arg;
|
||||
if (!nq) return;
|
||||
uint16_t best_rtt = node_best_rtt(nq);
|
||||
uint8_t data[12];
|
||||
memcpy(data, &nq->node_id, 8);
|
||||
data[8] = nq->conn_presence;
|
||||
data[9] = nq->conn_up;
|
||||
memcpy(data + 10, &best_rtt, 2);
|
||||
gui_bridge_post(GUI_EVT_NODEINFO_UPDATE, data, sizeof(data));
|
||||
}
|
||||
|
||||
#include "gui_bridge_impl.moc"
|
||||
Reference in new issue
Block a user