Commit Graph
2210 Commits
Author SHA1 Message Date
Evgeny f0bb03c2cf db_sync: datahash removed, Ed25519 signature mandatory, PK=(timestamp,author_signature), chain_hash includes signature, signed message=ts||json 2026-07-17 15:44:19 +03:00
Evgeny 05b24d36bb db_sync: fix dh_match premature sync complete — send tail when mc > tp+1
Root cause: db_handle_init_resp marked sync_state=2 when my_dh==peer_dh
without checking that all my records fit in the confirmed prefix.
If mc > tp+1 (I have records beyond the common prefix), the tail was
never sent — lost records.

Fix:
- Remove special-case 'sc==0 && my_dh==peer_dh' (redundant, same bug)
- In general dh_match: if mc > tp+1, send remaining records [tp+1,mc-1]
  using the same inline loop pattern as 'peer empty' branch

Test: 3 phases covering all dh_match paths:
- Phase 1: B empty+late instance → dh_match at tp=0 (sc=0) → tail-send 49
- Phase 2: A=80 B=50 → dh_match at tp=49 (sc>0, sparse) → tail-send 30
- Phase 3: fresh instances → peer empty → send all 30
2026-07-17 11:48:56 +03:00
Evgeny 2792586de7 db_sync: add INFO diagnostics for message sync flow tracing
- db_sync_on_conn_up: per-instance synced/skipped counters
- db_sync_peer_check_cb: summary INFO of check results
- db_sync_instance_add: peers_found + peers_synced counts
- db_handle_init_sync/initiate_sync: enhanced with tbl name
- db_handle_init_resp: tp + my_mc in sync complete/dh match
- db_handle_send_data: range + SYNC_DONE details; stop reason when mc>pk
- db_handle_sync_done: both counts + datahashes in mismatch; dh in confirm
- db_sync_recv_cb: INFO when instance NOT FOUND (timing race)
- cs_handle_channel_info_resp: sync readiness after channel ready
- cs_handle_welcome: note about db_sync peer_check timer
- on_db_sync_insert: counter (#1-3 then every 10) with ch/n/ts/dh/ct
2026-07-17 00:13:27 +03:00
Evgeny db67767405 fix: demote 6 crypto diagnostic logs from INFO to DEBUG
ECDH, ENCRYPT, DECRYPT, INIT_SEND, NORM_DECRYPT_TRY, INIT_DECRYPT_TRY
all moved to DEBUG_DEBUG — visible only with debug=crypto=debug
2026-07-16 23:35:08 +03:00
Evgeny 4fa5b0361f feat: show decoded invite details (node id, address:port) in JoinDialog
Auto-decodes invite link with 400ms debounce, shows 'Node: 0x... | IP:port'
2026-07-16 23:22:32 +03:00
Evgeny 55e3a7af94 fix: getInviteAddresses — use active direct-IP connections instead of DB peer list
Priority: iterate instance->connections for links with NAT_TYPE_DIRECT
(connected and reachable). Fallback: own socket addresses.
Removed broken getOnlinePeerAddresses() which returned other nodes' addresses.
2026-07-16 23:20:26 +03:00
Evgeny 2aa559acaf debug: add full ECDH/session-key diagnostics (6 points)
K1: sc_set_peer_public_key — priv, peer_pub, shared_secret, session_key
K2: sc_encrypt — session_key, tx_counter, nonce, plaintext
K3: sc_decrypt — session_key, nonce from packet, ciphertext_len
K4: INIT_SEND — salt, obfuscated_pubkey, peer_pubkey, my_pubkey, session_key
K5: NORM_DECRYPT_TRY — session_key, recv_len, rx_counter
K6: INIT_DECRYPT_TRY — session_key, recv_len, recv_len-40, salt, encrypted_pubkey

All via DEBUG_INFO(DEBUG_CATEGORY_CRYPTO) — enable with debug=crypto=info
2026-07-16 22:13:35 +03:00
Evgeny cdcc32cf84 fix: move DECRYPT FAIL/collision/reinit logs from DEBUG_CATEGORY_DEBUG to proper categories
- DECRYPT FAIL (1554): DEBUG_DEBUG → ETCP (main failure signal)
- not an init packet (1623): DEBUG_DEBUG → CONNECTION (was invisible ERROR)
- pkt_pool exhaust (1537): add ERROR log (was silent)
- REINIT/collision events (1473,1751-1838): DEBUG_DEBUG → CONNECTION
2026-07-16 22:03:33 +03:00
Evgeny 95061d3723 fix: demote INIT retry spam (link/send logs) to DEBUG_DEBUG
Keep at INFO only 'Sending INIT request' line per retry.
2026-07-16 21:41:50 +03:00
Evgeny 5b88d58dae fix: demote spam auto_connect logs to DEBUG_DEBUG
Remain at INFO: attempt + result FAIL. Demoted to DEBUG: TIMEOUT,
CANCELLED, GC closing, flight launched, AUTO_CONNECT in_progress.
2026-07-16 21:11:53 +03:00
Evgeny f039031883 fix: check conn_queue_entry->peer_node_id instead of conn->peer_node_id
etcp_conn_set_peer_node_id at state=0 updates conn->peer_node_id but
does not reindex the queue entry (key stays 0). Check the queue entry
directly to detect unindexed outbound connections.
2026-07-16 21:05:08 +03:00
Evgeny c3354938e1 fix: peers_* table creation + GUI_ERROR to log + cross-connect conn reuse
- chat_core.c: CREATE TABLE IF NOT EXISTS peers_* in ensure_channel_ready
- utun_node.cpp: GUI_ERROR redirected to debug log file via guiDebugFile()
- etcp_connections.c: reuse unindexed outbound conn (peer_node_id==0)
  on cross-connect INIT to avoid 'Can not insert link to socket'
2026-07-16 20:51:24 +03:00
Evgeny abee0ef3a9 chatgui: add --asan flag to build_linux.sh 2026-07-16 19:33:52 +03:00
Evgeny f3ac1cbb06 chat_sync: fix double-free in auto_connect — clear ca_state in ac_result_cb on success 2026-07-16 19:24:13 +03:00
Evgeny bfa3e666d4 fix test_uasync_socket_race: increase listen() backlog from 32 to 1024
Root cause: accept queue overflow (backlog=32) caused kernel SYN drops.
Children waited ~1s for SYN retransmit timeout (5 gaps × 1s = 5s out of 7.2s).
With backlog=1024 the timeout drops from ~7.2s to ~0.065s (110× faster).
2026-07-16 19:22:06 +03:00
Evgeny a8ce7d47b7 test_bgp_triangle: reduce keepalive_timeout from 2000ms to 200ms (10x speedup, 13.2s -> 1.27s) 2026-07-16 19:13:05 +03:00
Evgeny 3d04c37f56 stcp: add on_close callback to stcp_server_create/stcp_client_connect; member_sync: add join_ts/update_sig/update_ts fields, verify update_sig in apply; topo_node_sqlite: add join_ts/update_sig/update_ts to member_put, add member_get_join, add node_update_verified; chat_sync: include join_ts in join_msg, add update_sig/update_ts to CHANNEL_INFO_RESP; WELCOME verify join_sig; tests: use generated node_ids, reduce max ticks 2026-07-16 19:04:00 +03:00
Evgeny 0137a1bad4 chatgui: preserve input focus on chat refresh (save/restore focusWidget in loadChannel) 2026-07-16 13:03:23 +03:00
Evgeny 51d47ea6a8 chatgui: restore input focus after sending message 2026-07-16 12:54:34 +03:00
Evgeny c4d1f984bd chatgui settings: add Database tab with integrity check (quick/full) and optimize 2026-07-16 12:46:40 +03:00
Evgeny 03310db2cd test_chat_sync_stress: simplify to 20 batches, add profiling (avg per-record time, sync time, total) 2026-07-16 12:45:28 +03:00
Evgeny bb425c6722 db_sync v2: positional sync per-peer (synced_pos), datahash instead of chain_hash, no cascade on PUSH, single cascade after SEND_DATA batch, startup chain verification. PRAGMA synchronous=NORMAL + wal_autocheckpoint=10000 for performance. 2026-07-16 12:31:52 +03:00
Evgeny 0479c309bb Диагностика синхронизации: merkle_sync DEBUG_DEBUG логи обмена; убран спам auto_connect no IPv4; сохранение адреса инвайтера из ETCP; детали DECRYPT FAIL (link_state/enc_errs) 2026-07-16 00:41:51 +03:00
Evgeny 0d5a72c40e chat_sync: node_name теперь в пакетах — CHANNEL_INFO_RESP/JOIN/PEER_UPSERT передают имя, верификация использует имя из пакета (не из БД) 2026-07-16 00:32:09 +03:00
Evgeny 3f0fdad754 config_updater: поддержка создания конфига с нуля (без файла); новый файл — собирается с нуля, существующий — insert_or_replace 2026-07-15 23:47:00 +03:00
Evgeny e325b84a8e config: одно открытие файла — parse_config_from_buf вместо повторного fopen; убран read_file_to_mem 2026-07-15 23:39:01 +03:00
Evgeny ef24af7d24 Ключи: node_id из SHA-256(privkey) через весь конфиг; приоритет privkey — pubkey/node_id всегда выводятся из него; CHANNEL_INFO_RESP: верификация inviter_join_sig через ETCP-ключи 2026-07-15 23:13:29 +03:00
Evgeny da86841516 Диагностика: WARN при мутации конфига (ключи/node_id) + детали при invalid sig в JOIN/CHANNEL_INFO_RESP + предупреждение при расхождении node_id инвайта и ETCP 2026-07-15 22:44:33 +03:00
Evgeny 895eb0abbf Убрал спам-логи ETCP SEND/RECV/DECRYPT OK + добавил диагностику синхронизации мемберов (DEBUG_CATEGORY_DEBUG) в ключевые точки topo_group, merkle_sync, member_sync, chat_sync 2026-07-15 22:25:19 +03:00
Evgeny e708940bcd debug: upgrade router_deliver to DEBUG_INFO, show cb ptr
Router deliver now visible without trace — shows svc_id, len, remote_node_id, conn ptr, callback ptr
This will confirm whether CHANNEL_INFO_REQ reaches chat_sync on the server side
2026-07-15 22:06:54 +03:00
Evgeny d161782b46 fix: merkle_sync.c linked-list -> queue lookup, upgrade debug logs to INFO
- merkle_sync.c ms_find_conn_for_node: replace c=c->next with queue_find_data_by_index
- chat_sync.c cs_find_conn_for_node, cs_on_conn_up: DEBUG_DEBUG -> DEBUG_INFO
- etcp.c queue_set_ready: DEBUG_DEBUG -> DEBUG_INFO
2026-07-15 21:59:29 +03:00
Evgeny d71753fa79 debug: add diagnostic logs for chat invite connect flow
- cs_find_conn_for_node: show queue state, entry found/missing, conn flags
- cs_on_conn_up: log when skipping due to !initialized
- etcp_conn_queue_set_ready: log reindex details (old/new entry, count)
- etcp_conn_set_peer_node_id: show state+reindexed flag
2026-07-15 21:42:16 +03:00
Evgeny a7ecee01f5 etcp: replace connections linked-list with indexed ll_queue, add state/ref_count lifecycle
- Remove ETCP_CONN.next linked-list, UTUN_INSTANCE.connections list/count
- Unified connections in single ll_queue indexed by peer_node_id (0=pending)
- struct conn_queue_entry { peer_node_id, conn* } for uniform queue data
- Connection lifecycle via etcp.c: create→pending, conn_ready→indexed, close→detach+deferred free
- Close split: phase1 detach from external world, phase2 deferred via uasync_call_soon
- etcp_conn_set_peer_node_id: reindex on ID change (WARN)
- etcp_conn_ref_take/free: blocking close until refcount returns to 0
- Remove chat_connections — use unified connections queue directly
- Update all iteration/search patterns across 40 files (src + tests + chatgui)
2026-07-15 19:56:47 +03:00
Evgeny 6902f5fd95 chat: add ll_queue with index for P2P connections (replaces linear search)
- utun_instance.h: add chat_connections queue (indexed by node_id, 8 bytes)
- chat_sync.c: queue_new in init, queue_free in destroy, queue_find_data_by_index in cs_find_conn_for_node
- chat_sync.c: remove from queue in cs_on_conn_down
- chat_core.c: add to queue in connect_from_invite and connect_auto
- chat_core.c: remove from queue in cc_parallel_cleanup and ca_cleanup
- db_sync.c: replace linear conn search with queue_find_data_by_index (db_sync_send_hash)
2026-07-15 18:15:16 +03:00
Evgeny d0af503d01 config: fix allow_all parsing — accept yes/1/true like other bool options
- config_parser.c: allowed_keys_allow_all now uses strcasecmp(yes/1/true) instead of atoi()
- node_config.cpp: keep allow_all=yes
2026-07-15 18:01:54 +03:00
Evgeny 3368abad2a etcp+chat: add DEBUG_INFO logs for invite/crypto handshake debugging
- etcp_connections: DECRYPT FAIL now logs my_pub/peer_pub/session_ready at INFO level (debug category)
- chat_sync: log invite start with pubkey/node_id/addr_count
- chat_core: log pubkey set on invite connect (my_pub + peer_pub)
- joindialog: GUI_INFO on decoded invite
2026-07-15 17:53:25 +03:00
Evgeny d83d281fa0 config: add [allowed_keys] allow_all=yes by default, add [gui] as valid section
- node_config.cpp: add [allowed_keys] allow_all=yes to default config
- config_parser.c: add SECTION_GUI to suppress 'Key outside section' warnings
2026-07-15 17:34:48 +03:00
Evgeny 4c8e5f6223 db_sync+chat_sync+etcp: fix conn init race, reduce keepalive log spam
- etcp_connections: keepalive SEND/RECV/DECRYPT_OK: DEBUG→TRACE; DECRYPT_FAIL: WARN→DEBUG
- db_sync_on_conn_up: skip sync if !conn->initialized, wait for next UP event
- db_sync peer_check_timer+instance_add: also check conn->initialized
- chat_sync cs_on_conn_up: ignore conn_up before initialized (cs_send fails otherwise)
- db_sync_on_conn_up log now includes init= and links=
2026-07-15 17:25:14 +03:00
Evgeny 5b749d6cc8 chatgui: db_path is now a directory (chat_data/) with chats.db and sync/ inside
- Default db_path changed from 'chats.db' to 'chat_data' directory
- chat_core_init receives <db_path>/chats.db
- db_sync receives <db_path> (creates <db_path>/sync internally)
- Directory auto-created on startup via QDir::mkpath
2026-07-15 17:09:11 +03:00
Evgeny 6252556a02 chatgui: migrate message sync from chat_sync to db_sync
- Replace db_sync_stub.c with real src/db_sync.c in libutun
- Remove message sync protocol from chat_sync (INIT_SYNC/INIT_RESP/SEND_DATA/PUSH/ACK_PUSH/SYNC_DONE)
- Keep chat_sync auxiliary: join protocol, peer management, auto-connect
- Remove chat_core_insert_record, cursor_*, mark_sent/ttl_delete stubs
- chat_core on_db_sync_insert now only does SQLite INSERT + GUI notify
- Move db_sync_init() from instance_init_common to utun_instance_init for config override timing
- Force db_sync_enabled=1 in utun_node.cpp
- db_sync handles all P2P message sync via service 0x20
2026-07-15 17:02:47 +03:00
Evgeny e86944d661 style: reformat db_sync.c — break 500-char lines into readable ~130-char max 2026-07-15 16:32:36 +03:00
Evgeny acaa3a767c refactor: move chat_sync and member_sync to direct ETCP P2P, bypass etcp_router
Replace etcp_router_bind/etcp_route_send/etcp_router_unbind with
direct etcp_bind/etcp_send/etcp_unbind + find-conn-by-node_id helpers.
Same approach as db_sync (0x20). Service IDs unchanged (0x30, 0x31).
2026-07-15 16:13:45 +03:00
Evgeny d840b458a7 fix: pause router retransmits before clearing ETCP queues on reinit
When etcp_conn_reinit is called, it clears ETCP queues (input_wait_ack
etc.) which frees dgram objects to data_pool. If a router retransmit
timer fires concurrently, it sends through the same conn → normalizer
allocates from corrupted data_pool → SIGSEGV.

Fix: call etcp_router_pause_retrans_for_node() BEFORE etcp_conn_reset()
to cancel retrans timers and free inflight_q entries for all router
connections to the peer. No callbacks, no close notifications —
lightweight pause, router connections stay alive and resume when
ETCP connection comes back up.
2026-07-15 15:37:03 +03:00
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 f669254da3 feat: hard crash on etcp_connection_close from callback chain
Added callbacks_running flag to ETCP_CONN:
- set to 1 before up_cbks / down_cbks / ready_cbks iteration
- reset to 0 after iteration completes
- etcp_connection_close checks flag and does intentional SIGSEGV
  with FATAL log message if called during callback chain

This catches illegal synchronous close from within callbacks
instead of producing cryptic UAF segfaults later.
2026-07-15 14:43:47 +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 409a99f56b feat: cross-connect collision resolution via is_server master + collision flag
Protocol: added collision field to INIT_REQUEST_PKT (1 byte before ed25519_pubkey).
When two peers connect simultaneously, the one with is_server=0 (API-created
outbound link) is the master. Resolution by smaller node_id:
- We have master link + smaller node_id → send our INIT with collision=1
- We have master link + larger node_id → yield, process as slave
- Remote sends collision=1 → become slave unconditionally
- session_id change always forces reinit (genuine restart)

Removed unconditional etcp_conn_reinit on INIT_RESPONSE(0x03) — guarded by
reset_done flag. Server-side reinit now has collision check BEFORE reset_done
guard; session_id change penetrates reset_done protection.

Closes cross-connect reinit loop causing endless UP/DOWN flapping.
2026-07-15 13:53:15 +03:00
Evgeny 0912499309 fix: segfault in callback chain iteration — save next before invoke
In etcp_conn_ready / etcp_on_up / etcp_on_down / etcp_connection_create /
tcp_server_on_link, callback chains were iterated with:
  while (cbe) { cbe->fn(...); cbe = cbe->next; }
If the callback removes itself from the chain (e.g. ca_ready_cb calls
etcp_conn_remove_ready_cbk which u_free's the entry), cbe->next reads
freed memory → SIGSEGV.

Fixed by saving next pointer before invoking the callback:
  while (cbe) { n = cbe->next; cbe->fn(...); cbe = n; }
2026-07-15 12:46:37 +03:00
Evgeny abbb6de701 fix: block redundant conn reinit on cross-connect INIT (reset_done flag)
Problem: when two peers connect simultaneously, each incoming
INIT_REQUEST(0x02) or INIT_RESPONSE(0x03) triggers etcp_conn_reinit
unconditionally, causing endless UP/DOWN flapping loop.

Fix: add reset_done flag to ETCP_CONN:
- 0 at creation and after explicit reinit (reinit allowed)
- set to 1 in etcp_conn_ready (connection stable, block reinit)

Three call sites guarded with !conn->reset_done:
- client: handle_init_response_client (INIT_RESPONSE 0x03)
- server: existing link INIT_REQUEST processing
- server: new link INIT_REQUEST processing

send_reset logic preserved unconditionally — only etcp_conn_reinit
itself is blocked when already stable.
2026-07-15 12:17:14 +03:00
Evgeny 2bf7dcc6f0 debug: comprehensive connection diagnostics — recv/send/reinit paths
- RECV: log every packet (src addr, link found, session_ready, decrypt result)
- RECV: log init decrypt rejection with packet code (catches 0x03 INIT_RESPONSE
  silently dropped by init path)
- SEND: log destination addr+fd in send_init_response and etcp_encrypt_send
- REINIT: log full reason in server and client paths (code, session, got_init,
  initialized, links_up state before reinit)
2026-07-15 11:46:44 +03:00