- 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
- 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')
- CHAT groups don't send subnets and skip route insert/delete
- Group type mismatch sends ERR_GROUP_MISMATCH to peer
- New topo_groups_create_group() public API for creating typed groups
- 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
- NODEINFO_MSG (protocol, packed): added flags byte + group_id field
- NODEINFO (memory): ref_count, linked list heads instead of inline arrays
- NODEINFO_ROUTES: separate struct with linked list subnet heads
- NODEINFO_Q: node*, routes*, tranzit_data*, hop_list* as separate mallocs
- 6 memory_pools in ROUTE_BGP for NI_* linked list items
- ni_list_count() universal counter via _ni_head cast
- nodeinfo_serialize/deserialize for protocol <-> memory conversion
- NODEINFO_FLAG_SEND_SUBNETS controls subnet data in protocol
- group_id defaults: utun=NODEINFO_GROUP_UTUN(1) with subnets
Fixes:
- deserialization: data+2 instead of data+sizeof(BGP_NODEINFO_PACKET)
- memset: start after ll_entry to preserve ll.size
- hop_src: subtract hop_count*8 to point at correct dynamic offset
- same-ver branch: remove_path(conn) instead of remove_path_by_hop(peer)
- double-free in route_bgp_remove_conn/process_withdraw
- conn_mgr_add_alien_node: rewritten for new structures
- all test files updated for new API
Root cause: when bgp->local_node was reallocated (changed=1), old route
entries remained with stale v_node_info pointing to freed memory. The freed
memory got reused by a BGP peer's NODEINFO_Q, causing route_lookup to return
wrong node_id (b3b2b1b0afaeadac instead of local), which then failed at
etcp_route_send with 'no BGP route' and dropped packets to 10.23.2.1.
Changes:
- route_node.c: route_delete(old) before u_free + route_insert(new) after alloc
- utun_instance.c: remove duplicate route_insert (now atomic inside function)
- route_bgp.c: route_delete before freeing old peer NODEINFO_Q
- route_lib.c: routes_overlap now rejects only exact prefix+network duplicates
- tests/Makefile.am: add route_lib.o to test_route6_lib
When own NODEINFO is reflected back from a peer, do not add it
to bgp->nodes. Only update bgp->local_node which is sent separately.
This prevents route duplication and the 'local node in learned list'
inconsistency.
- route_bgp_process_nodeinfo: record alternative paths even when NODEINFO
version hasn't changed (fixes nodes disappearing on link down despite
having other active links)
- route_bgp_process_withdraw: only remove node when all paths gone (ret==1)
- route_bgp_remove_conn: broadcast withdraw for each removed node with
correct wd_source
- Extract ETCP_INIT_REQUEST_PKT / ETCP_INIT_RESPONSE_PKT named structs
- Replace anonymous structs and manual offset parsing with typed struct access
- Add src_ipv4/src_port fields (V2) to INIT REQUEST for DIRECT detection
- Server compares reported client addr with observed src; match + public IP → NAT_TYPE_DIRECT
- Skip STUN NAT check for DIRECT links
- route_bgp: handle NAT_TYPE_DIRECT → NAT_VERIFIED_DIRECT in handle_nat_info
- Add ed25519_public_key[32] to NODEINFO struct for pubkey distribution
- Add ed25519_public_key[32] to ROUTE_BGP (derived from X25519 privkey at init)
- Add ROUTER_FLAG_SIGNED (0x08) to SVC_ROUTE_HDR flags byte
- router_send_one_flags: when is_signed, sign [hdr][payload] and append 64-byte sig
- etcp_router_recv_cb: verify Ed25519 signature when ROUTER_FLAG_SIGNED set
- New API: etcp_router_conn_send_signed()
- Drop signed packets if sender node not in routing table or no Ed25519 key
- 5 unit tests in test_etcp_router_unit.c covering OK/tampered/unknown/no-key/short
- Rename NAT types: OPEN->EIM, RESTRICTED->STRICT across all code
- Add flat addr list {type,ip,port,socket_id} to NODEINFO (NODEINFO_IPV4_ADDR)
- Add NODEINFO_IPV4_SOCKET_META for per-socket metadata
- Add NODE_CONNECTIVITY with per-type probe status and min_rtt
- New module: route_connectivity.c/h (probing engine with socket fallback)
- STRICT verified addresses excluded from NODEINFO broadcast
- Trigger probing on new/updated BGP node, cancel on remove/withdraw
- Update NAT type names in etcpmon GUI
- route_bgp_send_nat_info: moved ip_to_str(pkt->nat_ip) log before etcp_send
- route_bgp_send_nat_check_req: moved ip_to_str(pkt->interface_ip) log before etcp_send
Both were reading from pkt memory that could be freed by etcp_send callback.
1. Добавлен via_conn в struct route_ping_pending - отслеживает через
какое соединение (third_conn) отправлен запрос на ping
2. route_ping_cancel_for_conn теперь отменяет pending при падении ЛЮБОГО
из двух conn: владельца линка (link->etcp) ИЛИ third_conn (via_conn)
3. nat_link_check_cb проверяет link->nat_check_status == IN_PROGRESS
перед обработкой - защита от race condition когда conn упал раньше
чем пришел ответ
4. Убраны избыточные DEBUG-логи, оставлены только информативные
- Исправлена критическая ошибка: использовалось na->link->conn вместо
na->link->etcp (struct ETCP_LINK.conn = ETCP_SOCKET*, а .etcp = ETCP_CONN*)
- Добавлен подробный дебаг в 4 места:
* route_ping_send_req_addr - при создании pending
* route_ping_cancel_for_conn - при поиске и отмене
* route_bgp_remove_conn - состояние линков перед отменой
* etcp_connection_close - очистка линков при закрытии
- route_bgp_remove_conn теперь отменяет pending NAT checks перед удалением
- Добавлена route_ping_cancel_for_conn: ищет pending запросы для conn,
отменяет таймеры, сбрасывает arg->link = NULL, удаляет из списка
- struct nat_check_arg вынесена в route_bgp.h для видимости из route_ping.c
- После отмены pending, статусы линков с NAT_CHECK_IN_PROGRESS сбрасываются в NONE
- etcp_connections.c: парсинг NAT IP через memcpy (сохраняет NBO)
- route_bgp.c: убраны ntohl() для IP в NAT detection и route_bgp_send_nat_info
- route_ping.c: убран htonl() для IP в ping request
- тесты: обновлены ожидания NBO для nat_ip
- platform_compat: get_interface_ip_by_index() для получения IP по ifindex
- ETCP_SOCKET: interface_addr заполняется из конфига/interface/default route
- BGP_NAT_CHECK_REQ: добавлены interface_ip/interface_port (network byte order)
- route_bgp_send_nat_check_req: отправляет interface_addr линка
- route_bgp_handle_nat_check_req: принимает interface данные в sockaddr-заглушку