Browse Source

gui update db and connection

chatgui
jeka 3 months ago
parent
commit
9dafb4c31e
  1. 2
      build.bat
  2. 2
      build_full.bat
  3. 7
      tools/chatgui/CMakeLists.txt
  4. 2
      tools/chatgui/build.bat
  5. 6
      tools/chatgui/build.sh
  6. 27
      tools/chatgui/src/channellist.cpp
  7. 1
      tools/chatgui/src/channellist.h
  8. 14
      tools/chatgui/src/mainwindow.cpp
  9. 1
      tools/chatgui/src/mainwindow.h
  10. 131
      tools/chatgui/transport/chat_sync.c
  11. 5
      tools/chatgui/transport/chat_sync.h
  12. 4
      tools/chatgui/transport/gui_bridge.h
  13. 6
      tools/chatgui/transport/gui_bridge_impl.cpp

2
build.bat

@ -28,4 +28,4 @@ if not exist "%MSYS2_PATH%\msys2_shell.cmd" (
REM Launch MSYS2 UCRT64 shell and run build script
echo Starting MSYS2 UCRT64 environment...
rem call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -c "bash build.sh > build_win.log 2>&1"
call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -defterm -no-start -c "bash build.sh 2>&1 | tee build_win.log"
call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -defterm -no-start -c "set -o pipefail; bash build.sh 2>&1 | tee build_win.log"

2
build_full.bat

@ -30,4 +30,4 @@ REM Launch MSYS2 UCRT64 shell and run build script with --full flag
echo Starting MSYS2 UCRT64 environment for FULL REBUILD...
echo Running: bash build.sh --full
echo.
call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -defterm -no-start -c "bash build.sh --full 2>&1 | tee build_full.log"
call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -defterm -no-start -c "set -o pipefail; bash build.sh --full 2>&1 | tee build_full.log"

7
tools/chatgui/CMakeLists.txt

@ -61,6 +61,7 @@ add_executable(chatgui
src/qrcode_utils.cpp
src/invite_link.cpp
src/invitedialog.cpp
src/joindialog.cpp
transport/msg_client.cpp
transport/crypto.cpp
transport/utun_node.cpp
@ -74,7 +75,11 @@ add_executable(chatgui
target_include_directories(chatgui PRIVATE ${CMAKE_SOURCE_DIR}/db)
target_compile_definitions(chatgui PRIVATE SQLITE_THREADSAFE=1)
set_source_files_properties(db/sqlite3.c PROPERTIES LANGUAGE C)
target_link_libraries(chatgui PRIVATE ${QT_LIBS} rlottie::rlottie ZLIB::ZLIB OpenSSL::Crypto ZXing::ZXing utun pthread dl)
if(WIN32)
target_link_libraries(chatgui PRIVATE ${QT_LIBS} rlottie::rlottie ZLIB::ZLIB OpenSSL::Crypto ZXing::ZXing utun pthread)
else()
target_link_libraries(chatgui PRIVATE ${QT_LIBS} rlottie::rlottie ZLIB::ZLIB OpenSSL::Crypto ZXing::ZXing utun pthread dl)
endif()
# ============================================================================
# Tests

2
tools/chatgui/build.bat

@ -23,7 +23,7 @@ echo.
set "CURRENT_DIR=%CD%"
call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -defterm -no-start -c "cd \"%CURRENT_DIR%/tools/chatgui\" && bash build.sh 2>&1 | tee build_win.log"
call "%MSYS2_PATH%\msys2_shell.cmd" -ucrt64 -here -defterm -no-start -c "set -o pipefail; cd \"%CURRENT_DIR%/tools/chatgui\" && bash build.sh 2>&1 | tee build_win.log"
set BUILD_RESULT=%ERRORLEVEL%

6
tools/chatgui/build.sh

@ -28,7 +28,11 @@ cmake --build "$BUILD_DIR" 2>&1 | tee -a "$LOG_FILE"
test ${PIPESTATUS[0]} -eq 0 || { log "Build FAILED"; exit 1; }
log ""
log "[3/3] Verifying..."
log "[3/3] Copying runtime DLLs..."
cp "$SRC_DIR/rlottie_build/librlottie.dll" "$BUILD_DIR/" 2>/dev/null && log " OK: librlottie.dll" || log " WARN: librlottie.dll not found"
log ""
log "[4/4] Verifying..."
EXE="$BUILD_DIR/chatgui.exe"
if [ -f "$EXE" ]; then
SIZE=$(du -h "$EXE" | cut -f1)

27
tools/chatgui/src/channellist.cpp

@ -2,7 +2,9 @@
#include "channeldelegate.h"
#include "../db/db_manager.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QPainter>
#include <QPixmap>
#include <QMenu>
@ -49,6 +51,31 @@ ChannelList::ChannelList(DbManager* db, QWidget *parent)
m_listView->setContextMenuPolicy(Qt::CustomContextMenu);
layout->addWidget(m_listView);
auto *footer = new QWidget(this);
auto *fl = new QHBoxLayout(footer);
fl->setContentsMargins(6, 4, 6, 4);
fl->setSpacing(6);
auto *gearBtn = new QPushButton(QString::fromUtf8("\xE2\x9A\x99"), footer);
gearBtn->setFixedSize(28, 28);
gearBtn->setStyleSheet(
"QPushButton { border: none; font-size: 18px; background: transparent; color: gray; }"
"QPushButton:hover { color: palette(text); }");
fl->addWidget(gearBtn);
fl->addStretch();
auto *plusBtn = new QPushButton("+", footer);
plusBtn->setFixedSize(28, 28);
plusBtn->setStyleSheet(
"QPushButton { border: 1.5px solid #3390EC; border-radius: 14px;"
" font-size: 18px; font-weight: bold; color: #3390EC; background: transparent; }"
"QPushButton:hover { background: #3390EC; color: white; }");
connect(plusBtn, &QPushButton::clicked, this, [this] { emit joinRequested(); });
fl->addWidget(plusBtn);
layout->addWidget(footer);
connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged,
this, [this](const QModelIndex &current, const QModelIndex &) {
if (current.isValid()) {

1
tools/chatgui/src/channellist.h

@ -18,6 +18,7 @@ public:
signals:
void channelSelected(const QString& channelId);
void inviteRequested(const QString& channelId);
void joinRequested();
private slots:
void onContextMenu(const QPoint& pos);

14
tools/chatgui/src/mainwindow.cpp

@ -3,6 +3,7 @@
#include "messagelist.h"
#include "accountlist.h"
#include "invitedialog.h"
#include "joindialog.h"
#include "invite_link.h"
#include "../db/db_manager.h"
#include "../transport/utun_node.h"
@ -42,6 +43,8 @@ MainWindow::MainWindow(QWidget *parent, DbManager* db)
connect(m_channelList, &ChannelList::inviteRequested,
this, &MainWindow::showInviteDialog);
connect(m_channelList, &ChannelList::joinRequested,
this, &MainWindow::showJoinDialog);
m_channelList->loadChannels();
m_accountList->loadAccounts();
@ -179,3 +182,14 @@ void MainWindow::showInviteDialog(const QString& channelId) {
InviteDialog dlg(link, this);
dlg.exec();
}
void MainWindow::showJoinDialog() {
if (!m_node || !m_node->isRunning()) {
QMessageBox::warning(this, "Error", "Node is not running.");
return;
}
JoinDialog dlg(m_node, m_db, this);
if (dlg.exec() == QDialog::Accepted) {
m_channelList->loadChannels();
}
}

1
tools/chatgui/src/mainwindow.h

@ -23,6 +23,7 @@ protected:
private slots:
void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
void showInviteDialog(const QString& channelId);
void showJoinDialog();
private:
void setupUi();

131
tools/chatgui/transport/chat_sync.c

@ -658,3 +658,134 @@ void chat_sync_connect_node(struct UTUN_INSTANCE* inst, uint64_t node_id) {
uint8_t req[8]; memcpy(req, &node_id, 8);
gui_bridge_call(GUI_OP_LOAD_NODEINFO, req, 8, NULL, NULL);
}
/* ── Invite link connect ── */
struct cs_invite_arg {
uint64_t node_id;
uint8_t pubkey[SC_PUBKEY_SIZE];
uint8_t* addrs_data;
int addr_count;
uint8_t* ch_id;
int ch_id_len;
};
static void cs_connect_result_cb(int result, uint64_t node_id, void* arg) {
(void)arg;
uint8_t data[12];
memcpy(data, &node_id, 8);
memcpy(data + 8, &result, 4);
gui_bridge_post(GUI_EVT_CONNECT_RESULT, data, 12);
}
static void cs_connect_from_invite_impl(void* arg) {
struct cs_invite_arg* a = (struct cs_invite_arg*)arg;
uint64_t node_id = a->node_id;
if (!g_cs || !g_cs->inst || !g_cs->inst->bgp || !g_cs->inst->conn_mgr) {
uint8_t err[12]; int r = -7;
memcpy(err, &node_id, 8); memcpy(err + 8, &r, 4);
gui_bridge_post(GUI_EVT_CONNECT_RESULT, err, 12);
goto cleanup;
}
struct ROUTE_BGP* bgp = g_cs->inst->bgp;
if (nodeinfo_find_by_id(bgp, node_id)) {
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chat_sync: node 0x%016llx already in BGP, connecting", (unsigned long long)node_id);
conn_mgr_connect_node(g_cs->inst->conn_mgr, node_id, 30000, cs_connect_result_cb, NULL);
goto cleanup;
}
size_t dyn_sz = (size_t)a->addr_count * sizeof(struct NODEINFO_IPV4_ADDR);
size_t data_sz = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry) + dyn_sz + 8;
struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(data_sz);
if (!nq) {
DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "chat_sync: failed to alloc NODEINFO_Q");
uint8_t err[12]; int r = -7;
memcpy(err, &node_id, 8); memcpy(err + 8, &r, 4);
gui_bridge_post(GUI_EVT_CONNECT_RESULT, err, 12);
goto cleanup;
}
struct NODEINFO* ni = &nq->node;
ni->node_id = node_id;
ni->ver = 0;
memcpy(ni->public_key, a->pubkey, SC_PUBKEY_SIZE);
memset(ni->ed25519_public_key, 0, SC_PUBKEY_SIZE);
ni->node_name_len = 0;
ni->local_v4_sockets = 0;
ni->local_v4_addrs = (uint8_t)a->addr_count;
ni->local_v6_sockets = 0;
ni->local_v6_addrs = 0;
ni->local_v4_subnets = 0;
ni->local_v6_subnets = 0;
ni->tranzit_nodes = 0;
ni->hop_count = 0;
uint8_t* dyn = (uint8_t*)ni + sizeof(struct NODEINFO);
const uint8_t* src = a->addrs_data;
for (int i = 0; i < a->addr_count; i++) {
struct NODEINFO_IPV4_ADDR* addr = (struct NODEINFO_IPV4_ADDR*)(dyn + i * sizeof(struct NODEINFO_IPV4_ADDR));
memset(addr, 0, sizeof(*addr));
uint8_t family = *src++;
if (family == 4) {
memcpy(addr->addr, src, 4); src += 4;
uint16_t port_be = ((uint16_t)src[0] << 8) | src[1]; src += 2;
addr->port = port_be;
addr->type = ADDR_TYPE_REAL;
addr->socket_id = 0;
addr->protocol = NODE_PROTO_UDP;
} else {
src += 18;
continue;
}
}
nq->alien = 0;
nq->dirty = 0;
nq->last_ver = 0;
nq->conn_mgr_type = CONN_TYPE_NONE;
nq->conn_mgr_intermediariy_count = 0;
memset(&nq->connectivity, 0, sizeof(nq->connectivity));
nq->best_socket = NULL;
queue_data_put_with_index(bgp->nodes, &nq->ll);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "chat_sync: created NODEINFO for 0x%016llx, %d addrs, connecting",
(unsigned long long)node_id, a->addr_count);
conn_mgr_connect_node(g_cs->inst->conn_mgr, node_id, 30000, cs_connect_result_cb, NULL);
cleanup:
u_free(a->addrs_data);
u_free(a->ch_id);
u_free(a);
}
void chat_sync_connect_from_invite(uint64_t node_id, const uint8_t* pubkey_bin,
const uint8_t* addrs_data, int addr_count,
const uint8_t* channel_id, int ch_id_len) {
if (!g_cs || !g_cs->inst || !g_cs->inst->ua) {
int r = -7;
uint8_t err[12]; memcpy(err, &node_id, 8); memcpy(err + 8, &r, 4);
gui_bridge_post(GUI_EVT_CONNECT_RESULT, err, 12);
return;
}
struct cs_invite_arg* a = u_calloc(1, sizeof(struct cs_invite_arg));
if (!a) return;
a->node_id = node_id;
memcpy(a->pubkey, pubkey_bin, SC_PUBKEY_SIZE);
size_t addrs_sz = (size_t)addr_count * 7;
a->addrs_data = u_malloc(addrs_sz);
if (!a->addrs_data) { u_free(a); return; }
memcpy(a->addrs_data, addrs_data, addrs_sz);
a->addr_count = addr_count;
a->ch_id = u_malloc((size_t)ch_id_len + 1);
if (!a->ch_id) { u_free(a->addrs_data); u_free(a); return; }
memcpy(a->ch_id, channel_id, (size_t)ch_id_len);
a->ch_id_len = ch_id_len;
gui_bridge_post_uasync(g_cs->inst->ua, cs_connect_from_invite_impl, a);
}

5
tools/chatgui/transport/chat_sync.h

@ -47,6 +47,11 @@ int chat_sync_push(struct UTUN_INSTANCE* inst,
/* Прослойка conn_mgr: загрузить nodeinfo из БД и подключиться */
void chat_sync_connect_node(struct UTUN_INSTANCE* inst, uint64_t node_id);
/* Подключиться к пиру по данным invite-ссылки (вызывается из GUI-потока) */
void chat_sync_connect_from_invite(uint64_t node_id, const uint8_t* pubkey_bin,
const uint8_t* addrs_data, int addr_count,
const uint8_t* channel_id, int ch_id_len);
#ifdef __cplusplus
}
#endif

4
tools/chatgui/transport/gui_bridge.h

@ -54,6 +54,10 @@ void gui_bridge_post(int event_type, const uint8_t* data, int data_len);
/* GUI → uasync: выполнить функцию в uasync-потоке */
void gui_bridge_post_uasync(struct UASYNC* ua, void (*fn)(void*), void* arg);
/* Callback for connect results (called from GUI thread) */
typedef void (*gui_connect_result_fn)(uint64_t node_id, int result);
void gui_bridge_set_connect_result_cb(gui_connect_result_fn cb);
#ifdef __cplusplus
}
#endif

6
tools/chatgui/transport/gui_bridge_impl.cpp

@ -29,6 +29,7 @@ public:
};
static GuiBridgeReceiver* g_receiver = nullptr;
static gui_connect_result_fn g_connect_result_cb = nullptr;
/* ── Трамплин для uasync_post: распаковывает результат и вызывает оригинальный callback ── */
@ -190,6 +191,7 @@ void GuiBridgeReceiver::processPost(int eventType, QByteArray data) {
uint64_t nodeId; int result;
memcpy(&nodeId, d, 8); memcpy(&result, d + 8, 4);
db->setNodeOnline(nodeId, result == 0);
if (g_connect_result_cb) g_connect_result_cb(nodeId, result);
}
break;
case GUI_EVT_NEW_PEER:
@ -247,6 +249,10 @@ void gui_bridge_post_uasync(struct UASYNC* ua, void (*fn)(void*), void* arg) {
if (ua && fn) uasync_post(ua, fn, arg);
}
void gui_bridge_set_connect_result_cb(gui_connect_result_fn cb) {
g_connect_result_cb = cb;
}
} /* extern "C" */
#include "gui_bridge_impl.moc"

Loading…
Cancel
Save