Commit Graph
5138 Commits
Author SHA1 Message Date
Evgeny 6cafff200b chatgui: add SIGINT/SIGTERM handler (as in utun.c), save scroll pos on every debounce
Signal handler via g_shutdown + uasync_wakeup ensures clean uasync poll exit.
updateReadPosition() now saves both lastReadMsgId and lastPosMsgId on every
scroll stop (300ms debounce), not just when read position changes.
connect(stopped, quit) triggers graceful Qt shutdown after uasync cleanup.
2026-07-24 03:47:15 +03:00
Evgeny 83ca0c65a4 chatgui: fix corrupted channel_id from non-null-terminated binary protocol
QString::fromUtf8(ch_id) read past length-prefixed string, capturing garbage.
Use fromUtf8(ch_id, ch_id_len) — length already available from bridge but was unused.
Messages now appear on refresh and unread badge correctly matches channel.
2026-07-24 03:33:14 +03:00
Evgeny fdc30d1a4e chatgui: synchronous DB write in saveChannelState/updateReadPosition, add shutdown debug logs
Replace gui_bridge_post_uasync_fn (async queue lost on shutdown) with direct
chat_core_save_ui_state (sync SQLite write). SQLite WAL handles concurrent access.
Add DEBUG_DEBUG traces in closeEvent, ~MainWindow, aboutToQuit.
2026-07-24 03:29:37 +03:00
Evgeny 393b7d36c8 chatgui: save scroll/read position on app quit via aboutToQuit
Make saveChannelState() public, connect to QApplication::aboutToQuit so
state is persisted on SIGINT, tray quit, or any other shutdown.
2026-07-24 03:24:54 +03:00
Evgeny 6ef21613c8 chatgui: pass author node_id in MSG_RECEIVED event, skip sound for own messages
Add author_node_id:8 to GUI_EVT_MSG_RECEIVED data format.
Callback now includes uint64_t author parameter.
SoundManager::play('msg_incoming') only when author != myNodeId.
2026-07-24 03:22:10 +03:00
Evgeny 37c5fa5607 chatgui: fix scroll jump on refresh, force debounce, add DEBUG logs
- Same-channel refresh: save scroll pos in memory, restore from memory (no DB race)
- Force m_readDebounce->start() after loadChannel (scrollToBottom may not trigger valueChanged)
- DEBUG_DEBUG logs in updateReadPosition, saveChannelState, onMessageReceived, setChannelUnreadCount
2026-07-24 02:59:15 +03:00
Evgeny 0c4862c66a chatgui: track read position via debounced scroll, only fully visible msgs are read
- Debounce timer (300ms) advances lastReadMsgId only when message is fully in viewport
- Unread badge no longer resets on channel select — only when actual scroll reads msgs
- saveChannelState() uses tracked m_lastReadMsgId instead of viewport bottom
- getChannels() reads lastReadMsgId from ui_state (was reading unused channels column)
2026-07-24 00:30:44 +03:00
Evgeny 216e516192 build: use explicit file list for liblmdb in CMake instead of GLOB
file(GLOB) + regex FILTER didn't work reliably on Windows. Replace with
explicit listing of mdb.c + midl.c (same as autotools).
2026-07-24 00:13:25 +03:00
Evgeny 726a4b8303 Revert unnecessary #ifndef _WIN32 guards in mplay.c — CMakeLists.txt filter handles exclusion 2026-07-24 00:03:03 +03:00
Evgeny e5dd41e5b2 build: exclude LMDB utilities from Windows CMake build, guard POSIX includes in mplay.c
file(GLOB) in libutun/CMakeLists.txt picked up mplay.c, mdb_dump.c and other
standalone LMDB tools that are not library code and fail on Windows. Filter them
out, keep only mdb.c + midl.c.
2026-07-23 23:58:39 +03:00
Evgeny 86d227bffe chatgui: remember last read message, restore scroll position, show unread count badge
Store read/scroll positions per channel via ui_state table (key-value).
Draw red +N badge on channel list items for unread messages.
Fix getMessages() to fetch last N messages (was fetching first N).
2026-07-23 23:47:35 +03:00
Evgeny de14f82048 chatgui: replace manual source lists with file(GLOB) in libutun/CMakeLists.txt
libutun/CMakeLists.txt: 151→84 lines (-67)
UASYNC_SOURCES: file(GLOB /*.c /liblmdb/*.c)
UTUN_COMMON_SOURCES: file(GLOB_RECURSE /*.c) excluding
  lwip_orig/, uip/, transport_layer/BBR/, utun.c
New .c files in src/ or lib/ are now automatically included.
2026-07-23 22:46:48 +03:00
Evgeny cf6108b1f1 chatgui: unify logging — debug_ui.h delegates to debug_config.h
debug_ui.h (50→10 lines): GUI_ERROR/WARN/INFO/DEBUG now delegate to
DEBUG_ERROR/WARN/INFO/DEBUG(DEBUG_CATEGORY_DEBUG, ...) from debug_config.h
Eliminates dual logging output, dual log file configuration.
Removed guiDebugFile() — debug_enable_file_output() already handles it.
Removed debug_ui.h include from utun_node.cpp (unused).
2026-07-23 22:45:26 +03:00
Evgeny 4aede4c6bd chatgui: extract MainWindow constructor into sub-methods
MainWindow (~15 lines): setupUi+setupTray+setupSoundFromConfig+
setupBridgeCallbacks+setupMessaging+setupNode+setupConnects
setupSoundFromConfig(): sound config parsing + loading
setupBridgeCallbacks(): 7 gui_bridge callback registrations
setupConnects(): 5 Qt signal connections
2026-07-23 22:44:32 +03:00
Evgeny 6c59ed43b2 chatgui: move crypto from MainWindow to transport layer
chat_channel.c: new chat_core_create_channel_auto(name) — generates
X25519/Ed25519 keys, random channel_id, Ed25519 signature, creates channel.
chat_core_create_channel_auto_trampoline for gui_bridge_post_uasync_fn.

mainwindow.cpp: onCreateGroupRequested() reduced from 100 to 15 lines.
Removed openssl/evp.h and openssl/rand.h includes from UI code.
2026-07-23 22:43:13 +03:00
Evgeny 3f662d85ba chat_core: split 912-line module into 5 files + delete dead chat_conn_mgr
chat_core.c (236 lines): init/destroy, getters, g_cc, helpers, si-registry
chat_msg.c (223 lines): submit_message, count, chain_hash, list_*, load_nodeinfo
chat_channel.c (197 lines): ensure_ready, create_channel, connect_channel, sign_join helper
chat_profile.c (189 lines): update_my_name, sync_my_addresses, save_ui_state
chat_status.c (118 lines): collect_status (NTP + ETCP connections)
chat_core_priv.h: shared g_cc extern + helpers

chat_conn_mgr.c/h: dead code (never compiled, never called)
CMakeLists.txt: add 4 new .c files to build
2026-07-23 22:41:28 +03:00
Evgeny 3448b0a482 channellist: fix dual blue selection — block signals + explicit select
- selectionCommand: remove Current flag to avoid redundant
  currentChanged emission during mouse press
- loadChannels: wrap clear+repopulate in blockSignals(true/false)
  to prevent selectionChanged and currentChanged from firing
  on intermediate model states
- selectChannel: use explicit selectionModel()->select() with
  ClearAndSelect + setCurrentIndex with NoUpdate
- simplified selection restore: only track selectedCid by ID,
  removed fallback-to-row logic
2026-07-23 21:31:00 +03:00
Evgeny 4ec930c8f0 chatgui: fix dual selection highlight and missing online count
- channellist.cpp: selectionChanged guard now checks currentIndex().row()
  is within model->rowCount() to avoid re-selecting stale index after
  model clear, which caused both channels to stay blue when switching.
- chat_sync.c: cs_refresh_channels now posts CHANNEL_PEERS_ONLINE
  for all channels after loading, fixing online count showing only
  on the last connected group.
2026-07-23 21:25:39 +03:00
Evgeny cbd9536a28 chatgui: fix invite link and Russian channel name encoding
- chat_sync.c: after invite trampoline, check if connection to invite
  node is already UP and trigger cs_on_conn_up to send CHANNEL_INFO_REQ.
  Fixes invite not completing when connection is reused (Fix 1 side effect).
- mainwindow.cpp: use name.toUtf8().constData() instead of qPrintable()
  to preserve UTF-8 encoding on Windows (Russian channel names).
2026-07-23 21:07:41 +03:00
Evgeny 23db012064 conn_mgr: fix duplicate connection and double-release bugs
- conn_mgr_connect_node: check instance->connections globally to reuse
  existing ETCP_CONN across groups instead of creating a new one (DUP addr)
- cm_start_phase_direct: close dead connection when etcp_link_new fails
  to prevent shadowing live connection in instance->connections hash
- cm_cleanup_db_node: remove redundant topo_node_registry_release
  (already done inside topo_node_free_lists)
2026-07-23 20:36:55 +03:00
Evgeny 58ad643516 Add debug logs to Ed25519 self-sig flow: computation, verification, skip due to no key 2026-07-23 20:00:11 +03:00
Evgeny 85269d1da3 Ed25519 self-signature in NODEINFO + fix sync sequence and zero-key bug
Add x25519_self_sig[64] to TOPOMSG_NODE/TOPO_NODE:
- topo_node.h: add field to both structs (wire format + memory)
- topo_node.c: compute Ed25519_sign(ed25519_privkey, x25519_pubkey) for own node
- topo_node.c: serialize/deserialize x25519_self_sig
- topo_group.c: verify Ed25519 self-sig on NODEINFO receive, reject forgery

Fix Ed25519 pubkey zero-key bug:
- topo_node_sqlite.c: get_ed25519_pubkey rejects all-zero key (MUST be non-zero)

Delay db_sync until Ed25519 key is available:
- db_sync.c: db_sync_on_conn_up checks db_get_ed25519_pubkey before starting
- db_sync.c: db_sync_peer_check_cb also checks Ed25519 key availability
- This prevents sync starting before NODEINFO with verified Ed25519 arrives
2026-07-23 19:55:15 +03:00
Evgeny 3890d2038d db_sync: add missing ERROR/WARN logs to all error branches
- db_record_insert: error logs for si_prep failures (SELECT, INSERT, cascade SELECT/UPDATE)
- si_parse_record: WARN logs for truncated header, data/sig overrun
- db_chain_hash_at: ERROR logs for missing row, corrupted blob
- db_prev_chain_hash: ERROR log for si_prep failure
- db_cascade_from: ERROR logs for si_prep failures
2026-07-23 18:16:53 +03:00
Evgeny acd4a189ae db_sync: add author_sig VERIFY FAIL diagnostics + SYNC_DONE retry limit
- db_verify_author_sig: show ed_pubkey and sig first bytes on failure
- SI_PEER: add sync_retry_count field
- db_handle_sync_done: limit re-initiate to 3 retries before giving up
- db_sync_initiate_sync / db_sync_on_conn_up: reset retry_count
2026-07-23 18:13:14 +03:00
Evgeny b48d3b4a77 db_sync: add diagnostic logs for message sync debugging during join
- db_handle_init_sync: TRACE→INFO with peer_cnt/my_cnt/tp_offset
- db_handle_send_data: detailed batch info (range, remaining count)
- db_sync_initiate_sync: add table name to log
- db_sync_on_conn_up: add first table name to summary log
2026-07-23 16:47:22 +03:00
Evgeny 3e95cf5ca6 fix: dialog hangs on join success + remove per-packet spam logs
- chat_sync.c: move pending_invite clear from INFO_RESP to WELCOME,
  post GUI_EVT_CONNECT_RESULT on invite success in cs_handle_welcome
- etcp_connections.c: NORM_DECRYPT_TRY/CRYPTO_DECRYPT_OK DEBUG_DEBUG->TRACE
- secure_channel.c: ENCRYPT/DECRYPT DEBUG_DEBUG->TRACE
2026-07-23 16:36:40 +03:00
Evgeny 4f831703f0 fix: etcp_conn_set_peer_node_id переиндексация при state=0 + conn_mgr ставит peer_id сразу 2026-07-23 16:19:03 +03:00
Evgeny 511a2dcd06 fix: авто-подключение Phase 2/3 — запрос всех нод из node_addresses, без привязки к peers_<ch> 2026-07-23 14:41:22 +03:00
Evgeny 196c2896d3 debug: sochet count after instance_init (категория debug, видно при текущем конфиге) 2026-07-23 14:17:58 +03:00
Evgeny 01a0a568a6 debug: crypto_ctx session_key логгирование — CRYPTO_CONN_READY, CRYPTO_ON_UP, CRYPTO_DECRYPT_OK, DECRYPT_FAIL+seskey 2026-07-23 14:04:44 +03:00
Evgeny 3e0a4e0eb1 fix: замена malloc на u_strdup в channelSelected — u_free падал на чужой памяти 2026-07-23 13:12:04 +03:00
Evgeny 0e324cf36d chat_core: connect_channel API — запуск topo_group_connect_init при выборе канала из GUI, убрано дублирование создания групп в utun_node 2026-07-23 12:51:45 +03:00
Evgeny be258eea4d fix: remove stale peers_* CREATE TABLE from chat_core, drop ORDER BY node_RTT
chat_core_ensure_channel_ready() had a duplicate CREATE TABLE peers_*
with OLD schema (no node_RTT, node_type, connected). Since it was called
from 4 places WITHOUT topo_node_sqlite_channel_put() first, the old
schema was created first, and IF NOT EXISTS in the new DDL was a no-op.

Removed the entire old block. Only topo_node_sqlite_channel_put() now
creates peers_* tables with the full schema.

Also removed ORDER BY p.node_RTT from get_public_peers/get_local_peers —
ordering not needed for sequential connect attempts.
2026-07-23 00:24:16 +03:00
Evgeny 8facce46ac feat: auto-connect Phase 3 (local/netif addresses) + restart fix
Phase 1: connected peers (connected=1)
Phase 2: direct/EIM (addr_type=1,2), exclude self
Phase 3: local/strict NAT (addr_type=0,3), exclude self
Timeout: 5000→2000ms per attempt
Restart: DOWN triggers reconnect when phase=DONE & active=0

Debug logs: init, Phase1 per-peer, UP phase info, restart branches
2026-07-22 23:55:44 +03:00
Evgeny 7dee05c628 fix: node_registry crash — TOPO_NODE_REG_ENTRY node/lldata overlap
struct TOPO_NODE_REG_ENTRY имел node и ll.data[0] (гибкий массив) на одном смещении.
memcpy(re->ll.data, &node_id, 8) затирало re->node значением node_id,
из-за чего node_registry_find возвращал не указатель а битый node_id → SIGSEGV.

Убрал struct TOPO_NODE_REG_ENTRY, перешёл на явные смещения:
data[0..7]=ключ, data[8..15]=указатель, queue_entry_new(16).
2026-07-22 23:05:04 +03:00
Evgeny 6edd40d141 topo_group_connect: авто-подключение CHAT-групп + conn_mgr_connect_from_invite + замена chat_conn_mgr в chatgui
Добавлено:
- conn_mgr_connect_from_invite() — подключение к новому узлу по invite-данным
  (INIT → INVITE_INFO_REQ/RESP → проверка членства в группе → сохранение в БД)
- topo_group_connect.c — авто-подключение при старте CHAT-группы:
  Phase 1: одновременный connect всех connected=1 пиров, таймаут, отмена незавершённых
  Phase 2: последовательный перебор публичных адресов до первого успеха
- Счётчик active_conn_count с проверкой nodeinfo-путей (UP/DOWN)
- restart() при phase=DONE и count==0

БД:
- connected INTEGER NOT NULL DEFAULT 0 в peers_<ch> + ALTER TABLE для существующих
- topo_node_sqlite_set_connected / get_connected_peers / get_public_peers

Chatgui:
- Включён topo_group (убран utun_instance_set_topo_group_enabled(0))
- Создание TOPO_GROUP_TYPE_CHAT при channel_ready и при старте
- Invite connect через conn_mgr_connect_from_invite
- Удалён chat_conn_mgr (из сборки) + весь старый auto-connect код
2026-07-22 22:48:12 +03:00
Evgeny 4215349349 topo_recovery: каскадное восстановление узлов с группировкой по next_hop
При разрыве ETCP-соединения модуль собирает каскадно отвалившиеся узлы:
- add_node из hop_list вычисляет next_hop относительно failed_peer,
  группирует узлы в отдельные recovery-контексты (direct/indirect списки)
- start запускает асинхронный перебор для каждой группы параллельно
- is_next_hop-узел пробуется первым с приоритетом по мин. RTT
- таймаут 2с на попытку, conn_mgr_cancel_callback при отмене
- отмена: topo_group_new_conn (on_up) находит узел в любом ctx -> ctx целиком
- завершение: оба списка пусты -> освобождение ctx
2026-07-22 19:01:55 +03:00
Evgeny f6b37a857b conn_mgr: bind to topo_group, DB node loading, configurable DIRECT timeout, tests
- conn_mgr_init(TOPO_GROUP* group) — работает внутри заданной группы
- conn_mgr_connect_node: загрузка узла из SQLite если нет в BGP-таблице
- topo_node_sqlite_node_load(): загрузка TOPO_NODE (ref=0) из БД
- cm_start_phase_direct: db_loaded-ветка — перебор всех адресов без NAT-фильтра
- cm_cleanup_db_node: удаление TOPO_NODEQ из группы при неудаче, только если нет путей
- cm_start_phase_indirect: исправлено зависание при best_candidates==0 (cm_deliver_result)
- conn_mgr_set_direct_timeout_ms(): конфигурируемый таймаут фазы DIRECT
- conn_mgr_destroy до etcp_router_destroy (исправлен порядок)
- test_conn_mgr: +2 сценария (DB-успех, DB-недоступен), проверка topo_group
2026-07-22 17:33:58 +03:00
Evgeny 852ce401e7 Добавлен group_id в etcp_router и topo_group, удалён msg_transport
- etcp_router: SVC_ROUTE_HDR (+8B), ETCP_ROUTER_CONN/TRANSIT_QUEUE хеши расширены под group_id
- Все caller'ы (proxy, routing, conn_mgr, nat, chatgui, tests) обновлены
- topo_group: глобальный реестр TOPO_NODE по node_id, ref_count=0 при создании
- BGP-обмен активируется для всех групп (а не только дефолтной)
- Протокол: group_id добавлен в WITHDRAW/TABLE_REQ/TABLE_COMPLETE/ERR_GROUP_MISMATCH
- Per-connection коллбэки заменены на instance-level conn_status
- msg_transport полностью удалён из проекта
57/57 тестов
2026-07-22 15:51:03 +03:00
Evgeny 5265783164 fix: self node online=0 after chat_core_init refactor — add topo_node_sqlite_node_set_online(self, 1) 2026-07-22 13:54:36 +03:00
Evgeny e2d9879636 refactor: remove direct nodes table writes from chat_core/conn_mgr, use topo_node_sqlite API
- chat_core_init: replace INSERT INTO nodes with topo_node_sqlite_node_update_verified, remove redundant topo_node_sqlite_init call
- chat_core_update_my_name: replace UPDATE nodes with topo_node_sqlite_node_update_verified
- chat_conn_mgr_connect_from_invite: simplify invite node insert (x25519 only, no ed25519)
- topo_node_sqlite: add detailed column comments to peers table DDL (both server and chatgui)
- chat_core: add detailed column comments to peers table CREATE TABLE
2026-07-22 13:38:17 +03:00
Evgeny 7aa4a34f35 fix chatgui: members showing offline after JOIN — always refresh channel cache before posting online count 2026-07-22 12:19:59 +03:00
Evgeny a7346c25e3 fix chatgui: members not showing (schema mismatch) and username showing JSON instead of name
- topo_node_sqlite_member_put: remove joined_at column from INSERT (not in server schema, duplicates join_ts)
- chat_core: rename peers table column name→userinfo to match server schema + add ALTER TABLE migration
- chat_sync: remove 3 redundant INSERT INTO nodes that wrote raw JSON userinfo into nodes.name, overwriting correct plain name from topo_node_sqlite_node_update_verified
2026-07-22 12:03:57 +03:00
Evgeny df809f251c ntp: use NTP-corrected time everywhere instead of unixepoch()/gettimeofday
- db_sync_next_timestamp(): ntp_time_get_us() via si->db_sync->inst
- topo_node_sqlite_node_put: +time_t now_sec param, replace unixepoch()
- topo_node_sqlite_node_update_verified: +time_t created_at param
- topo_node_sqlite_member_put: joined_at = join_ts (already NTP-corrected)
- All INSERTs (nodes, local_identity, accounts, peers):
  replace DEFAULT(unixepoch()) with explicit ntp_time_get_seconds()
- ON CONFLICT DO UPDATE: created_at = COALESCE(nodes.created_at, excluded.created_at)
- Updated callers: topo_group.c, chat_sync.c, chat_conn_mgr.c, chat_core.c
2026-07-22 11:39:10 +03:00
Evgeny fab1c77cfb chatgui: remove unused addServer/addClient/removeServer/removeClient 2026-07-22 10:22:37 +03:00
Evgeny 6574c58257 chatgui: unify config update logic, fix node_id derivation, fix test
- config_updater.{h,cpp}: single implementation — config_update_in_lines
  for batch updates + config_update_option for file-level. REPLACE/APPEND
  modes, section auto-creation
- node_config.cpp: generateIdentity() now derives node_id via
  SHA256(pubkey) (like sc_derive_node_id_from_pubkey) instead of random.
  save() uses config_update_in_lines for line-level update when file
  exists, saveFull() only for new file and addServer/addClient.
  Removed duplicate findSectionBounds/updateOptionInSection/configUpdateOption
- test_config_updater.cpp: Q_ASSERT replaced with VERIFY macro — Q_ASSERT
  in Release mode does not evaluate the expression, causing false positives.
  Test now works in both Debug and Release
2026-07-22 10:13:40 +03:00
Evgeny ab252a0984 chatgui: include platform_compat.h for htole64 on Windows 2026-07-22 09:23:35 +03:00
Evgeny b1cbd5acf9 topo_node_sqlite: dynamic idx_sql allocation instead of fixed 128-byte buffer 2026-07-22 09:18:54 +03:00
Evgeny 2785845acf platform_compat: use #include <process.h> instead of getpid macro 2026-07-22 09:13:36 +03:00
Evgeny b1bf27d023 fix Windows warnings: getpid, htole64, gettimeofday, socket_t mismatches, radix min 2026-07-22 09:08:19 +03:00