#include "gui_bridge.h" #include #include #include #include #include extern "C" { #include "../../../lib/u_async.h" #include "../../../lib/mem.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 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) { QString chId = QString::fromUtf8((const char*)d + 1, chLen); qDebug("gui_bridge: MSG_RECEIVED ch=%s", qPrintable(chId)); if (g_msg_received_cb) g_msg_received_cb((const char*)d + 1, chLen); } else { qWarning("gui_bridge: MSG_RECEIVED invalid data length %d", dlen); } } else { qWarning("gui_bridge: MSG_RECEIVED data too short %d", dlen); } break; case GUI_EVT_CONNECT_RESULT: if (dlen >= 12) { uint64_t nodeId; int result; memcpy(&nodeId, d, 8); memcpy(&result, d + 8, 4); qDebug("gui_bridge: CONNECT_RESULT node=0x%016llx result=%d", (unsigned long long)nodeId, result); if (g_connect_result_cb) g_connect_result_cb(nodeId, result); } else { qWarning("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); qDebug("gui_bridge: NEW_PEER node=0x%016llx", (unsigned long long)nodeId); } else { qWarning("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); qDebug("gui_bridge: CHANNEL_UPDATED ch=%s", qPrintable(chId)); } } else { qWarning("gui_bridge: CHANNEL_UPDATED data too short %d", dlen); } break; default: qWarning("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) 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 && fn) uasync_post(g_ua, fn, arg); } 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; } } /* extern "C" */ #include "gui_bridge_impl.moc"