- dedup double ETCP_CONN_STATUS_UP (UDP+TCP links) in topo_group_new_conn
- close conn_mgr handle on TIMEOUT in Phase2/3 (fix stuck 'already connecting')
- infinite Phase1→2→3 cycle with pause (1s active / 30s standby)
- CHAT_EVT_CONNECTING_NODES: yellow circle in member list while connecting
- Android: client_activity wiring via onStart/onStop + nativeSetActive
- function-level comments in topo_group_connect.c
- client_activity: desktop/server now ACTIVE by default, only mobile starts STANDBY
- topo_group_connect: endless Phase1→2→3→1 cycle until connected
- Pause between failed Phase2/3 attempts: 1s active, 30s standby
- on_down always triggers cycle_restart when active_conn_count=0
- re-init destroys previous state and starts fresh
- CHAT_EVT_CONNECTING_NODES event notifies GUI of current connecting nodes
- Android: ConfigProvider default mode='auto', PTT fix, UDP log timer fix
- Добавлен device_type (1 байт, CLIENT_TYPE_*) в INIT_REQUEST и INIT_RESPONSE
- Добавлен keepalive_interval (2 байта) в INIT_RESPONSE
- STCP handshake расширен с 43 до 46 байт (device_type+keepalive)
- negotiate_keepalive(): оба desktop/server → min, иначе (есть mobile) → max
- keepalive_interval вынесен в UTUN_INSTANCE для использования в handshake
- stcp_client_connect() принимает device_type и keepalive_interval
- peer_device_type/peer_keepalive_interval передаются через stcp_link в ETCP_LINK
- ntp_node_time.c: respond to TIME_SYNC only when peer is unsynced (not always)
Prevents infinite 10-byte ping-pong that ate bandwidth when both sides synced.
- pkt_normalizer.c: add in_total_pkts/in_total_bytes increments in
etcp_input_ready_cb (real send path), matching pn_packer_send (test path).
- conn_mgr_core.c/conn_mgr_priv.h: full INVITE_INFO_RESP with channel info
auto_socket.c: create_iface_tcp_socket returns stcp_server* instead of int,
ifa->v4_tcp/ifa->v6_tcp now properly track the created server, preventing
duplicate bind/listen on every reconcile_iface call.
etcp_connections.c: tcp_socket_add now resolves interface_addr via
get_interface_ip_by_index/get_interface_ipv6_addr_nl for any type (not just
PUBLIC), preventing NAT TCP v4 sockets from being destroyed due to INADDR_ANY.
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
- stcp_server: send handshake response BEFORE on_ready to prevent ETCP INIT data mixing into client recv buffer (crc mismatch)
- conn_mgr: relax peer_node_id match for INVITE_INFO_RESP when peer_node_id==0 (STCP connections)
- chat_tcp_test: remove invalid 'local' outside function
- etcp_connections.h: add WIRE_OVERHEAD, IP_UDP_OVERHEAD_V4/V6, SC_ENCRYPT_OVERHEAD
(properly accounts for v6 IP(40)+UDP(8)+SC(3)+CCM tag(16) = 67 vs old UDP_HDR_SIZE=28)
- etcp_connections.c etcp_encrypt_send: use WIRE_OVERHEAD instead of UDP_HDR_SIZE
- etcp_connections.c send_init_response: clamp padding to max_data = mtu - WIRE_OVERHEAD
- chat_core_priv.h: add addr_type_from_ip() classifier
- chat_profile.c, chat_sync.c, member_sync.c: use classified addr_type instead of hardcoded 0
- chat_sync.c: skip zero nat_addr in JOIN, fall back to interface_addr
- topo_node_sqlite.c, member_sync.c: remove addr_type=0 filter from SELECT/DELETE
- chat_profile.c, member_sync.c: DELETE all addresses (not just addr_type=0)
- node_put/node_update_verified: set online=1 on INSERT (nodes created when conn is UP)
- channel_peers_all: fix peer_needed calculation (atl byte was missing)
- cs_send_channel_join: add proto byte to address serialization matching all parsers
- auto_socket.c/h: создание/удаление UDP сокетов автоматически при изменении интерфейсов через netlink/route socket
При auto_sockets=yes пропускает ручные [server] сокеты
Тип сокета: PUBLIC если публичный IP, иначе NAT
Для новых сокетов добавляются линки ко всем активным NCD-соединениям
При удалении интерфейса линки убираются, сокет закрывается
Platform-agnostic API для использования из Android/chatgui
- node_conn_direct.h/c: ncd_add_socket_links / ncd_remove_socket_links — управление линками на конкретном сокете
- socket_monitor.h/c: экспорт socket_monitor_update_if_addr для auto_socket
- config_parser.h/c: опция auto_sockets в [global]
- init_sockets(): пропуск ручных сокетов при auto_sockets=yes
- utun_instance: интеграция auto_socket_init/destroy
- media_delivery: fix stack-buffer-overflow ack[3] → ack[9]
- topo_node: fix heap-use-after-free в topo_group_update_my_nodeinfo — сохранение node_id/ver перед registry_store, использование return value
conn_mgr_router_recv_handler (etcp_router_bind): DIRECT_REQ, INTERM_EXCHANGE, DISCONNECT
conn_mgr_direct_recv_handler (etcp_bind): INVITE_INFO_REQ, INVITE_INFO_RESP
Each transport path now has its own handler — no more mixed concerns.
svc_id=17 (ETCP_RT_ID_CONN_MGR) is a singleton resource — bind once
at utun_instance_init, unbind once at utun_instance_destroy.
Previously each conn_mgr (one per group) called bind/unbind separately,
causing 'overwriting' and 'not bound' WARNs on every group init/shutdown.
Handler dispatches by group_id from message — no need for per-group binding.
- etcp_on_up: list up-link addresses after connection summary
- etcp_on_down: show all link addresses that were lost
- Link UP (server/client): add addr=X
- Connection established: add addr=X
- Link closed: add addr=X before traffic stats
- Link down (keepalive timeout): add addr=X
Now: [conn] Link 1 UP (server, mtu=1600, addr=192.168.40.247:2122)
- member_sync apply_items: empty payload is normal sync completion, not error
- topo_node_sqlite node_load: no addresses is normal for stub/seed nodes
- conn_mgr_core: node skipped when not in routing (normal for nodes w/o addrs)
- topo_group send_nodeinfo: downgrade ERROR→WARN in DEBUG category
- db_sync INIT_RESP: protocol details belong in DEBUG, not INFO
cm_invite_fail and cm_handle_invite_info_resp: always close invite's NCD
handle before freeing the invite struct. Previously the NCD close was
skipped when nq->handle != NULL (success path never closed it at all),
leaving cm_invite_ncd_callback registered with a dangling pointer.
On subsequent NCD DOWN event the stale callback caused SIGSEGV.
- _compute_bucket_hash: SELECT protocol, write proto byte
- _member_get_items: SELECT protocol, write proto byte
- _member_apply_items: consume proto byte in skip calculation
- topo_node_sqlite_channel_peers_all: SELECT protocol, write proto byte
All 5 writers and 5 readers now consistently include protocol byte.
- stcp_server_create: support AF_INET and AF_INET6 V6ONLY=1 (no dual-stack)
- Add listen_family to stcp_link_config
- init_sockets: return error (not partial) on any bind failure
- add chat_core_sync_my_addresses() call at chatgui startup
- collect_my_addrs: add proto byte (1=UDP, 2=TCP) to binary format
- chat_sync.c JOIN/WELCOME/PEER_UPSERT: read proto byte, write protocol column
- member_sync.c: read proto byte, dynamic protocol bind
- topo_node.c: debug logs for nodeinfo changed detection
- node_config.cpp: type=public for all servers
- conn_mgr_core.c: убрана запись node_name из cm_handle_invite_info_resp
- topo_node_sqlite.c: name в nodes не перезаписывается пустой строкой
- android_jni_bridge.c: bridge_get_node_name читает peers_<ch>.userinfo если nodes.name пуст
node_conn_direct:
- ncd_init_cb: skip UP when links_up==0, ncd_up_cb delivers when link comes up
- close/force_close: handle_count safety checks, callback clearing
- open/open_node case 2: create links on reused dead conn
- ncd_create_links: skip duplicate link on same conn (stale->etcp==conn)
- set_callback: optional callback change on live handle
conn_mgr:
- cm_ncd_callback: DOWN only delivers event (handle stays alive)
- cm_ncd_callback: TIMEOUT force_close BEFORE cm_deliver_event
- cm_deliver_event: read handle fields to locals before callback (reentrany-safe)
- INVITE_INFO_REQ/RESP: add duplicate cmd byte for direct-send protocol
- cm_handle_invite_info_resp: search invite by group_id in channel conn_mgr
Android:
- node_id computed by sc_derive_node_id_from_pubkey in C, not Kotlin
- utun_bridge_join_channel: recompute node_id, log mismatch
- invite_link_c: compute nodeId from pubkey via sc_derive_node_id_from_pubkey
- NativeLib.deriveNodeId, InviteLink.kt uses C function
- CONN_MGR entries: replace dynamic array with ll_queue (hash=256, key_size=8)
cm_find_entry now O(1) via queue_find_data_by_index
cm_ensure_entry uses queue_entry_new + queue_data_put_with_index
cm_entry_cleanup removes from queue and frees entry
- TOPO_GROUP_NODE: replace handles** array with single CONN_MGR_HANDLE*
remove topo_node_handle_register/unregister/count — dead indirection
nq->handle = h / nq->handle = NULL in all call sites
- TOPO_GROUP_NODE: remove dead fields dirty, best_socket, tranzit_data/count
dirty replaced with local variable in nat_detection.c
tranzit_data removed from wire format (TOPOMSG_NODE), serialize, deserialize
update struct layout: one field per line with comments
- New files: transport_layer/socket_monitor.c/h — socket state monitoring with per-instance ctx
- etcp_api: expose get_latency/1s_pkt_count measuring, add etcp_hashrnd for tests
- utun_instance: store socket_monitor per instance, add is_socket_ok check
- topo_node: detect IPv4 addresses with port from listening sockets
- topo_group: use node_name for display in routes
- Makefile.am: add socket_monitor.c to build
- CM_V6_ANY for :: socket (matches all v6 addr classes)
- sin6_scope_id from s->netif_index (not from local_addr where :: has scope=0)
- getnameinfo in stcp_link_connect to preserve scope_id in addr string
- scope_id in cm_invite_tcp_connect, ncd_create_links, connect_create_links_v6, cm_bg_ping_to_node
Android chatgui:
- New MemberListScreen with member list, detail card, edit dialog
- Link status dots (green/red/grey) per address in detail card (1s poll)
- Self-node name coloured green
- ChatScreen: people icon in TopAppBar
IPv6 autoconnect fixes (3 bugs in conn_mgr/topo):
- topo_node_sqlite_node_load: load v6 addresses from DB
- topo_node_registry_store: merge v6_addrs into existing node
- cm_sock_v6_classify: wildcard [::] treated as CM_V6_DIR
- cm_add_v6_link: htons(port) was missing
Memory fixes:
- strdup→u_strdup in bridge (7 instances)
- u_realloc cap update before success check (3 instances)
- char sql[256]→[512] for truncated SELECT
Chat member hash now includes addresses for change detection
Linux chatgui:
- Link status dots in AccountList detail panel (1s poll)
- Self-node name in green in member list