Commit Graph
144 Commits
Author SHA1 Message Date
Evgeny 9378b18ce7 fix: defer connection_close in ready_cb using uasync_call_soon
ca_ready_cb and cc_parallel_ready_cb called etcp_connection_close
synchronously on non-selected connections from within the ready_cbk
callback chain. This corrupts senders_list in topo_group, causing
UAF in topo_group_start_link_nat_check.

Now uses uasync_call_soon (zero-delay timer) to defer the close
to the next event loop iteration, after the callback chain completes
and callbacks_running flag is reset.
2026-07-15 15:00:05 +03:00
Evgeny 371208d489 chatgui: выпилить все записи в БД из GUI потока (DbManager)
- DbManager теперь read-only, получает sqlite3* handle через setDb()
- chat_core — единственный владелец БД (SQLITE_OPEN_FULLMUTEX + WAL)
- initTables/seedStubData/createChannel/insertMessage/setUiState удалены из DbManager
- seed 5 stub-аккаунтов перенесён в chat_core_init()
- GUI_EVT_DB_READY — уведомление о готовности БД
- setUiState заменён на QSettings
- каналы загружаются по DB_READY коллбэку
- убран двойной sqlite3_open (один файл, один хендл)
2026-07-15 14:26:32 +03:00
Evgeny f7d88e5532 fix segfault in ca_ready_cb: ca_state owns all ca_ctx, single cleanup point
- Added struct ca_ctx** ctxs to ca_state (parallel array)
- ca_cleanup now frees all ctxs[i] and the ctxs array
- ca_ready_cb: removed u_free(ctx), added etcp_conn_remove_ready_cbk before cleanup
- ca_timeout_cb: removed u_free(ctx) — ctx lives until ca_cleanup
- All error paths set ctxs[i]=NULL for ca_cleanup safety
2026-07-15 11:21:31 +03:00
Evgeny 1e7585438d chat_core_connect_auto: add outbound conn to inst->connections
etcp_connection_create does NOT add conn to inst->connections list.
Without this, incoming INIT handler can't find the outbound conn
by peer_node_id and creates a new one, causing insert_link collision.
2026-07-15 11:05:27 +03:00
Evgeny a8164baf41 chat_core_connect_auto: set peer_node_id on ETCP_CONN
Without peer_node_id, incoming INIT handler can't find the existing
outbound connection, creates a new one, and fails on insert_link collision.
2026-07-15 10:51:53 +03:00
Evgeny 0adf7d07ef chat_core_connect_auto: dedup addresses by (addr,port) 2026-07-15 10:32:06 +03:00
Evgeny 33aa6bbd5a auto-connect: cursor-based, no close on timeout, GC every 1s, cancel API
- ca_timeout_cb: removed etcp_connection_close, ETCP lives past 3s timeout
- ca_state.cancelled flag + chat_core_connect_auto_cancel() for external cancel
- chat_core_connect_auto returns ca_state* via out_state
- Rewritten auto_connect: cursor (ch,peer) instead of bulk collect
- GC every 1s: closes flights with no link_status after 3s
- ac_result_cb no longer clears ca_state (GC handles cleanup)
- stop: cancels all flights via chat_core_connect_auto_cancel
2026-07-15 10:24:44 +03:00
Evgeny dccf54b30b auto-connect + GUI per-channel indicators
- chat_core_connect_auto: direct ETCP connect from SQLite (no BGP)
- auto_connect: parallel connect to peers with 3s timeout, retry 10s
- RTT saved to node_addresses on disconnect
- vertical status bar + circle badge with online count per channel
- ChannelListView prevents deselection
2026-07-15 06:00:43 +03:00
Evgeny 1a0229fd4f add NTP time synchronization module 2026-07-14 20:14:00 +03:00
Evgeny f3719a28df fix: change timestamp unit from microseconds to milliseconds
- db_sync.c: last_timestamp_us → last_timestamp_ms, use tv_sec*1000 + tv_usec/1000
- db_sync_stub.c: same change
- QDateTime::fromMSecsSinceEpoch() in chatgui expects milliseconds
- 1 µs → 1 ms change fixes 'minutes ticking like seconds' display bug
2026-07-14 19:33:16 +03:00
Evgeny 5fc621690a fix: wall-clock timestamps + merkle_sync timeout + build script
- Replace get_time_us() with utun_gettimeofday() for PUSH message timestamps
  (db_sync.c, chat_core.c) — monotonic clocks differ across Linux/Windows
- Fix merkle_sync: restart session timer in _handle_request to prevent
  double-sided timeout when both nodes start member_sync simultaneously
- Fix INIT_RESP short-format: don't mark synced when my_count > peer_count
- Add db_sync_get_last_timestamp() to avoid duplicate timestamp generation
  between db_sync and chat_core on_db_sync_insert
- Fix db_sync_stub to generate timestamps consistently
- build.sh: auto-rebuild chatgui via CMake after utun build
2026-07-14 19:23:02 +03:00
Evgeny 4636a69225 fix chatgui: pass chain_hash in PUSH + start member_sync on server join
chat_sync_push: add chain_hash parameter, use it instead of zeros
  (fixes chain_hash mismatch → all PUSH messages were rejected)

on_db_sync_insert: pass computed chain_h to chat_sync_push

cs_handle_channel_join: call member_sync_start for the joiner
  (server now initiates member sync when client joins.
  Previously merkle_sync was only started by client → timeout
  because server never responded)

cs_handle_welcome: add DEBUG_INFO before member_sync_start on client side
2026-07-14 18:43:04 +03:00
Evgeny f9f516c2e9 fix chatgui: PUSH new messages to peers + comprehensive debug logging
chat_sync_push: fix PUSH format to match cs_handle_push expectations
  (was missing insert_record header: ts+dh+nid before ct+dlen+data)
  Add DEBUG_INFO log with peer count after send.

on_db_sync_insert: call chat_sync_push after successful local insert
  → new messages are now pushed to all connected peers
  Add DEBUG_ERROR to 4 silent returns (JSON parse fail, SQL errors)

chat_core_submit_message: add DEBUG_INFO entry log (ch, ct, len)

chat_core_insert_record: add DEBUG_WARN/ERROR to 7 silent returns
  (truncated record, SQL prepare fail, unknown step error)

cs_handle_push: add DEBUG_INFO for ACK send, DEBUG_ERROR for insert fail

cs_handle_send_data: DEBUG_WARN when record truncated mid-loop

cs_on_conn_up: DEBUG_INFO sync path with channel count

Full trace now shows every message: SUBMIT → insert → PUSH → RECV PUSH → ACK
2026-07-14 18:34:24 +03:00
Evgeny 58b9f28149 fix chatgui: prevent invite deadlock on connection flap
cs_on_conn_down: remove invite state zeroing on disconnection.
Only timeout callbacks and explicit protocol end (CS_MSG_ERROR,
transition to JOIN phase) clear the invite state.

Connection flap now causes automatic retry:
  conn_up → pending_invite_ch_id != 0 && !info_req_timer → resend
  CHANNEL_INFO_REQ. No deadlock possible.
2026-07-14 18:22:05 +03:00
Evgeny 8c41b44718 fix chatgui: repair INIT_RESP handler, add debug logging to all sync handlers
- cs_handle_init_resp: change silent reject len<37→len<5 (actual payload
  sent is 6 bytes, plen=5 after stripping type byte).
  Support short format (synced, peer_count+sparse_count) and long format
  (divergence, with test_pos+peer_ch). Add INFO logs at each decision.
  (fixes sync never starting after invite join — RECV INIT_RESP len=5
  was silently rejected)

- All 12 silent return branches in handlers: add DEBUG_WARN with
  handler name, peer, ch_id, and reason (makes malformed packets
  visible in logs)

- Key sync flow INFO logs:
  cs_handle_init_sync: peer_count, my_count
  cs_handle_send_data: records sent/received count
  cs_on_conn_up: invite vs sync path
  chat_core_insert_record: successful insert
2026-07-14 18:07:57 +03:00
Evgeny 2d179ec41d fix chatgui: message format, member notify, chain_hash sync
- on_db_sync_insert: parse JSON {"n":...,"ct":...,"d":...}, store
  d→data, n→node_id, ct→content_type with proper chain_hash
  (fixes JSON displayed instead of message text)
- chat_core_cursor_open: SELECT chain_hash column
- chat_core_cursor_next: include chain_hash(32) in output record
- cs_handle_send_data: parse chain_hash in received records
  (fixes chain_hash mismatch → all sync records were dropped)
- cs_handle_channel_join: post GUI_EVT_MEMBERS_CHANGED
  (fixes creator not seeing new member after join)
- cs_handle_welcome: trigger INIT_SYNC with inviter after join
  (fixes no message sync after invite join)
2026-07-14 17:46:33 +03:00
Evgeny c4751557b1 fix chatgui: ensure msg table + db_sync instance on join and restart
- chat_core_ensure_channel_ready(ch_id): idempotent — creates
  msg_<id> table + registers db_sync instance if missing
- chat_core_create_channel: refactored to use ensure_channel_ready
- cs_handle_channel_info_resp: call ensure_channel_ready on join
- chat_core_init: iterate existing channels on restart
- Fixes 'no such table: msg_<id>' after invite join
- Fixes 'no db_sync instance for ch=<id>' after restart
2026-07-14 17:22:01 +03:00
Evgeny 4254ab97bb fix chatgui: db_sync_stub + chat_sync_init for invite link join
- db_sync_stub.c: complete rewrite — proper structs, all API functions
  (db_sync_instance_add, insert_signed, set_insert_cb, select)
  Fixes db_sync_instance_add returning NULL (inst->db_sync was NULL)
- libutun/CMakeLists.txt: remove src/db_sync.c, stub replaces it
- chatgui/CMakeLists.txt: add transport/db_sync_stub.c
- utun_node.cpp: remove redundant db_sync_init/destroy,
  add chat_sync_init/destroy — server now registers svc_id=48
  Fixes 'no handler for svc_id=48' on incoming CHANNEL_INFO_REQ
2026-07-14 17:03:00 +03:00
Evgeny ccd25813f6 refactor: extract merkle_sync — universal Merkle-tree sync module
- merkle_sync.h/c: tree (5-level prefix, SHA256 buckets), wire protocol
  (HASHES/REQUEST/BATCH), sessions (10s timeout, 3 retries), async API
  with done_cb
- member_sync: thin glue layer, implements 3 data model callbacks
  (update_bucket_hash, get_items, apply_items) for chat members
- chat_sync: updated member_sync_start() calls with done_cb callback
- member_tree_hash table renamed to merkle_tree_hash
- member_sync.h public API preserved, internal tree/wire logic removed
2026-07-14 16:35:58 +03:00
Evgeny f617dcd68e db_sync: LMDB→SQLite, multi-instance, etcp_api, chatgui integration
- src/db_sync: LMDB replaced with SQLite (separate tables per instance: db_sync_name_id)
  TTL index (author, timestamp), WAL mode, per-instance peers/timers
  opaque DB_SYNC_INSTANCE* handle, insert callback, select API
  new fields: author_signature, delivered_peers, delivery_chain
  transport: etcp_api direct P2P (was etcp_router)

- src/db_sync.h: user-oriented API docs, multi-instance lifecycle

- lib/Makefile.am: liblmdb sources removed
- lib/sqlite3.c+h: SQLite amalgamation added

- topo_node: LMDB→SQLite (src/topo_node_sqlite.c moved from chatgui)

- chatgui: real db_sync.c replaces db_sync_stub.c
  chat_core: db_sync_insert_signed + dual-write insert callback
  utun_node: db_sync_init/destroy replaces chat_sync_init/destroy
  CMakeLists: stubs removed, real db_sync.c added
2026-07-14 14:17:43 +03:00
Evgeny 37417ba49d Fix: my_node_name insert inside [global] section, add button tooltips in channellist 2026-07-14 09:17:01 +03:00
Evgeny cca3511503 fix: replace deprecated SHA256 API with EVP, conditional dl linkage for Windows 2026-07-14 09:07:03 +03:00
Evgeny d70cdbb040 chatgui: preserve active channel selection on reload, members sync, profile settings, member list model 2026-07-14 08:52:10 +03:00
Evgeny c3f946fb63 chat_sync: fix join group stall — remove node_id match in cs_on_conn_up, add CS_MSG_ERROR protocol response 2026-07-13 18:11:18 +03:00
Evgeny 0c2eeb8820 chatgui: validate config options on startup, refuse to start on errors 2026-07-13 15:46:20 +03:00
Evgeny 637b21da9e debug: remove console_level/file_level — simplified output routing
Remove secondary level filtering in debug_output(). Now the only filter
is debug_should_output() (per-category + global fallback). Output goes
to file (if file_output set) or console (if console_enabled), with no
additional level check.

Removed:
- debug_set_console_level(), debug_set_file_level()
- console_level, file_level fields from debug_config_t
- debug_set_level() no longer sets console_level
2026-07-13 15:38:08 +03:00
Evgeny 6bf267924d add DEBUG_CATEGORY_CONNECTIVITY for handshake/protocol lifecycle logs
New category (id=25) replaces DEBUG_CATEGORY_DEBUG in chat_sync and
chat_core. This allows enabling only protocol-level logs (SEND/RECV,
timeouts, handshake) without the noise from DEBUG category.

Changes:
- debug_config.h: add CONNECTIVITY=25, COUNT→26
- debug_config.c: add 'connectivity' to g_debug_categories
- chat_sync.c: DEBUG→CONNECTIVITY in all protocol logs
- chat_core.c: DEBUG→CONNECTIVITY in connection/create logs
- utun_node.cpp: remove hardcoded DEBUG=TRACE (now config-driven)
- chatgui.cfg: connectivity=info in debug_categories
2026-07-13 15:14:48 +03:00
Evgeny 5318476cdf chat_sync: add protocol request timeouts and SEND/RECV debug logs
- Add info_req_timer (5s) for CHANNEL_INFO_REQ — reports CONN_MGR_ERR_TIMEOUT
  to GUI on timeout, clears pending invite state
- Add join_timer (8s) for CHANNEL_JOIN → WELCOME — reports timeout on failure
- cs_on_conn_down: cancel all proto timers, reset pending invite state
- cs_send: log every outgoing message (SEND <type> to=<peer> ch=<id> len=<n>)
- Dispatcher: log every incoming message (RECV <type> from=<peer> ch=<id> len=<n>)
- Add cs_msg_name() helper for readable message type names
- pending_invite_node_id/ch_id no longer cleared immediately after send —
  kept until response or timeout, enabling proper error reporting
2026-07-13 15:06:06 +03:00
Evgeny 43d95016ae fix: send INIT_RESPONSE with reset when server creates new connection after restart
When server restarts, new ETCP_CONN has session_id=0 (calloc).
If client sends INIT_REQUEST_NOINIT (0x04) with session_id=0,
the condition conn->session_id != session_id is false (both 0),
so no reset was sent. Client kept old seq numbers while server
expected seq=1, causing 'Waiting for initial packet' deadlock.

Fix: add || new_conn to the condition — when server created a
fresh connection (was restarted), always send reset to client.
2026-07-13 14:19:27 +03:00
Evgeny 89b1a01448 invite+clipboard+conn_mgr: sock_meta for alien nodes, clipboard fix, bg_ping fix
- chat_core_connect_from_invite: add TOPO_SOCKMETA4 (id=0, UNKNOWN, UNKNOWN)
  so cm_has_direct_ip/cm_start_phase_direct can match socket_id=0 addr
- conn_mgr: cm_bg_ping_timer_cb reads real addr from nq->node->v4_addrs
  instead of NULL; added cm_bg_ping_noop_cb per required etcp_send_ping_to_socket
- invitedialog: set both QClipboard::Clipboard and Selection on Linux/X11
2026-07-13 09:37:46 +03:00
Evgeny 2d93dd66c8 chatgui: fix Windows build - replace netinet/in.h with socket_compat.h 2026-07-13 08:08:27 +03:00
Evgeny 85a91a1320 chatgui: invite link connect flow + GUI_ERROR always-on diagnostics
- debug_ui.h: remove NDEBUG guard so GUI_ERROR works in Release builds
- invite_link.h/cpp: add error field to InviteData with specific failure reason
- joindialog: show exact decode error in QLabel instead of generic message
- chat_sync: implement invite connect flow (CHANNEL_INFO_REQ/RESP, JOIN, WELCOME)
- topo_node_sqlite: node/address table init and lookup
- utun_node: getInviteAddresses fallback from ETCP sockets
- minor fixes in mainwindow, chat_core, gui_bridge
2026-07-13 08:06:19 +03:00
Evgeny 102816d0dc node_config: load() returns true on parse success; main: specific diagnostics per missing field 2026-07-13 07:52:49 +03:00
Evgeny c65940f499 Copy Qt platforms/qwindows.dll plugin alongside executable 2026-07-13 07:44:06 +03:00
Evgeny 79bdafc9a7 Optimize recursive DLL resolution: scan only newly added DLLs 2026-07-13 07:43:25 +03:00
Evgeny cb1021f231 Recursive DLL dependency resolution via objdump for build.sh windeployqt fallback 2026-07-13 07:36:51 +03:00
Evgeny 58503907b5 Use objdump -p for smart DLL dependency discovery as windeployqt fallback 2026-07-13 07:33:49 +03:00
Evgeny 666507d3fe Move Qt DLL deployment from CMake to build.sh (windeployqt + manual fallback) 2026-07-13 07:30:56 +03:00
Evgeny f0f20c158b Simplify windeployqt: use PATH, add diagnostics, --no-compiler-runtime 2026-07-13 07:23:35 +03:00
Evgeny ed5ccd1ffb Add windeployqt post-build step for automatic Qt DLL deployment on Windows 2026-07-13 07:19:37 +03:00
Evgeny 65611790fa Fix enterEvent signature for Qt5/Qt6 compatibility 2026-07-13 07:06:58 +03:00
Evgeny de7841f33a chatgui: create group, unified logging, fix uasync_post epoll bug
- Add CreateGroupDialog with group name input
- Generate X25519+Ed25519 keypairs, random uint64 channel_id,
  Ed25519 signature, write to DB via uasync thread
- chat_core_create_channel(): create msg table, topo_node_sqlite_channel_put()
- GUI_EVT_CHANNEL_UPDATED notification to reload channel list
- Per-category debug config: debug_level= + debug_categories= in [gui]
- Unified logging via debug_config: all threads write to same file/console
- debug_enable_console(1) to mirror file output to stderr
- DEBUG_LEVEL_DISABLED=-1: truly disable category, NONE=0 fallback to global
- Fix uasync_post under epoll: process_posted_tasks was never called
- Fix MainWindow constructor parameter ordering (dbPath vs debugFile)
- debug_ui.h: append mode ('a' instead of 'w')
2026-07-12 17:39:20 +03:00
Evgeny 28e5950d29 TOPO_BGP -> TOPO_GROUP: multi-group support
- Renamed TOPO_BGP to TOPO_GROUP with topo_group_id (64bit)
- Added TOPO_GROUPS container (ll_queue group_list) in UTUN_INSTANCE
- Memory pools moved from TOPO_GROUP to TOPO_GROUPS (instance-level)
- Default group: TOPO_GROUP_UTUN = 0x8000000000000000
- topo_groups_get_default() searches by group_id, not just first entry
- All topo_bgp_* renamed to topo_group_*; function signatures updated
- Files: topo_bgp.h/c -> topo_group.h/c
2026-07-09 18:08:49 +03:00
Evgeny 3c3d9a65d9 refactor: переименование route_node/route_bgp в topo_node/topo_bgp
Файлы: route_node.* route_node_lmdb.* route_bgp.* -> topo_node.* topo_node_lmdb.* topo_bgp.*

Структуры:
- ROUTE_BGP -> TOPO_BGP, ROUTE_BGP_CONN_ITEM -> TOPO_BGP_CONN_ITEM
- NODEINFO -> TOPO_NODE, NODEINFO_Q -> TOPO_NODEQ, NODEINFO_PATH -> TOPO_NODEPATH
- NODEINFO_ROUTES -> TOPO_NODESUBNETS, NODE_CONNECTIVITY -> TOPO_CONNECTIVITY
- wire: NODEINFO_MSG -> TOPOMSG_NODE, NODEINFO_IPV4_* -> TOPOMSG_*4 и т.д.
- memory: NI_IPV4_* -> TOPO_*4, NI_IPV6_* -> TOPO_*6
- ROUTE_SUBCMD_* -> TOPO_SUBCMD_*, ETCP_ID_ROUTE_ENTRY -> ETCP_ID_TOPO_ENTRY

Функции:
- route_bgp_* -> topo_bgp_*
- nodeinfo_* -> topo_node_*
- route_node_* -> topo_node_*
- route_node_lmdb_* -> topo_node_lmdb_*

Смысл: отделение механизма формирования топологии узлов от IP-роутинга.
2026-07-09 17:01:56 +03:00
Evgeny 62954ca0a9 chatgui: replace MsgClient/ChatPropagator/crypto with chat_core, update DB/messaging/layout 2026-07-08 21:15:45 +03:00
Evgeny 1889d23240 metrics: RTT/loss histograms + Ed25519 signing + peer exchange via INIT handshake + file logging to stats/<peer>.dat
- etcp_metrics struct: 12-bucket RTT histogram, 11-bucket loss histogram, 10-min snapshots (>=200 pkts)
- Total counters: packets/bytes sent/rcvd, losses (retrans + probe gap detection)
- CSV append to <stats_dir>/<peer_id>.dat every 10 min
- Ed25519 pubkey exchange in INIT handshake (V3), always present
- Signed metrics exchange via ETCP_SECTION_METRICS (0x0A)
- Received metrics saved as from_<peer_id>.dat with signature hex
- on_metrics_rcvd callback in ETCP_BINDINGS
- stats_dir derived from config file path, mkdir'd at instance init
- Simplified versioning: ETCP_INIT_REQ_SIZE / ETCP_INIT_RESP_SIZE via sizeof
2026-07-07 17:16:45 +03:00
Evgeny f5c93266dc security: hardening flags + control_server fixes (F-001, F-002)
- Add --hardened flag to build.sh with FORTIFY, stack protector, PIE, RELRO
- Add --enable-hardening to configure.ac
- F-001: fix %s -> %.32s to prevent stack leak from non-null-terminated network string
- F-002: add pre-check recv_len >= MAX before buf_space computation to prevent size_t underflow
2026-07-07 07:47:37 +03:00
jeka 861d81815f gui update db and connection 2026-07-06 21:57:52 +03:00
jeka 9dafb4c31e gui update db and connection 2026-07-06 21:52:46 +03:00
Evgeny 19a4505a03 chat_sync: новый протокол синхронизации чата вместо ChatPropagator
- gui_bridge.h/cpp — кросс-поточные асинхронные коллбэки uasync↔GUI
- chat_sync.h/c — протокол синхронизации (INIT_SYNC/RESP, SEND_DATA, PUSH/ACK, SYNC_DONE)
- DbManager полностью переписан: per-channel таблицы msg_<ch> + peers_<ch>,
  4 ключа в channels, signature, protocol/rtt в node_addresses, sync-методы
- ChatPropagator удалён, заменён на chat_sync
- db_sync_stub.c — заглушки для сборки chatgui без LMDB-версии db_sync
- db_schema.md актуализирован под новую схему
2026-07-06 16:25:52 +03:00