#ifndef CONN_MGR_PRIV_H #define CONN_MGR_PRIV_H #include "conn_mgr.h" #include #include "../lib/ll_queue.h" #include "etcp_api.h" #include "secure_channel.h" #include "../transport_layer/node_conn_direct.h" #include "topo_node.h" struct UTUN_INSTANCE; struct ETCP_CONN; struct ETCP_LINK; struct ETCP_SOCKET; struct ETCP_ROUTER_CONN; struct TOPO_GROUP_NODE; struct TOPO_GROUP; struct stcp_link; struct stcp_client; /* ═══════ константы ═══════ */ #define CONN_MGR_MAX_CANDIDATES 3 #define CONN_MGR_CANDIDATE_STALE_TB 300000 #define CONN_MGR_CANDIDATE_PING_TB 20000 #define CONN_MGR_BG_PING_INTERVAL_TB 1000 #define CONN_MGR_BG_PING_CYCLE_MIN_TB 600000 #define CONN_MGR_LOCAL_SCAN_ATTEMPTS 3 #define CONN_MGR_LOCAL_SCAN_TIMEOUT_MS 100 #define CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS 2000 #define CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS 3000 #define CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS 15000 #define CONN_MGR_REVERSE_RETRANSMIT_MS 1000 #define CONN_MGR_EXCHANGE_RETRANSMIT_MS 1000 #define CACHE_MS 20000 /* время жизни RTT-замера ~20с (через cm_is_rtt_fresh, мс) */ #define CONN_MGR_MAX_INTERMEDIARIES 3 /* ═══════ состояния ═══════ */ enum CONN_MGR_STATE { CONN_MGR_STATE_DISCONNECTED = 0, CONN_MGR_STATE_CONNECTING = 1, CONN_MGR_STATE_CONNECTED = 2, CONN_MGR_STATE_FAILED = 3, }; enum CM_TRY_STATE { CM_TRY_NONE = 0, CM_TRY_PENDING = 1, CM_TRY_OK = 2, CM_TRY_FAILED = 3, }; /* ═══════ протокол CONN_MGR (ETCP_RT_ID_CONN_MGR) ═══════ */ enum { CM_SUBCMD_DIRECT_REQ = 0x01, CM_SUBCMD_DIRECT_RESP = 0x02, CM_SUBCMD_INTERM_EXCHANGE_REQ = 0x03, CM_SUBCMD_INTERM_EXCHANGE_RESP= 0x04, CM_SUBCMD_INTERM_SELECTED = 0x05, CM_SUBCMD_DISCONNECT = 0x06, }; struct CONN_MGR_CANDIDATE { uint64_t node_id; uint16_t rtt; } __attribute__((packed)); #pragma pack(push, 1) struct CM_DIRECT_REQ { uint8_t cmd, subcmd; uint32_t request_id; uint8_t addr_count; }; struct CM_DIRECT_RESP { uint8_t cmd, subcmd; uint32_t request_id; uint8_t accepted; }; struct CM_EXCHANGE_REQ { uint8_t cmd, subcmd; uint32_t request_id; uint8_t candidate_count; struct CONN_MGR_CANDIDATE candidates[4]; }; struct CM_EXCHANGE_RESP { uint8_t cmd, subcmd; uint32_t request_id; uint8_t my_count, your_count; struct CONN_MGR_CANDIDATE my_candidates[4], your_candidates[4]; }; struct CM_INTERM_SEL { uint8_t cmd, subcmd; uint32_t request_id; uint8_t count; struct CONN_MGR_CANDIDATE selected[3]; }; struct CM_DISCONNECT { uint8_t cmd, subcmd; uint64_t node_id; }; #pragma pack(pop) #define CM_DIRECT_REQ_H_SIZE (sizeof(struct CM_DIRECT_REQ)) #define CM_DIRECT_RESP_HDR_SIZE (sizeof(struct CM_DIRECT_RESP)) #define CM_EXCHANGE_REQ_SIZE (sizeof(struct CM_EXCHANGE_REQ)) #define CM_EXCHANGE_RESP_SIZE (sizeof(struct CM_EXCHANGE_RESP)) #define CM_INTERM_SEL_SIZE (sizeof(struct CM_INTERM_SEL)) #define CM_DISCONNECT_SIZE (sizeof(struct CM_DISCONNECT)) /* ═══════ внутренние структуры ═══════ */ struct cm_reverse_pending { struct cm_reverse_pending* next; uint32_t request_id; struct CONN_MGR_ENTRY* entry; uint8_t* pkt; size_t pkt_len; }; struct cm_exchange_pending { struct cm_exchange_pending* next; uint32_t request_id; struct CONN_MGR_ENTRY* entry; void* timer; struct CM_EXCHANGE_RESP cached; uint8_t received, probed; uint8_t* pkt; size_t pkt_len; }; struct CONN_MGR_HANDLE { uint64_t node_id; uint64_t group_id; conn_mgr_cb_t cb; void* cb_arg; struct CONN_MGR_ENTRY* entry; struct CONN_MGR_HANDLE* next; void* deliver_up_token; /* токен отложенного cm_deliver_up_cb (uasync_call_soon), NULL если не постился/уже сработал */ }; struct CONN_MGR_ENTRY { struct ll_entry ll; /* ll_queue entry — первый элемент */ uint64_t node_id; /* хеш-ключ 8B, offset от data = 0 */ uint8_t state, conn_type; uint64_t last_traffic_tb; struct CONN_MGR_HANDLE* handles; struct NODE_CONN_DIRECT* ncd_handle; uint8_t ncd_down_notified; uint64_t intermediaries[3]; uint8_t intermediariy_count, rr_idx; uint8_t local_scan_state, main_connect_state, db_loaded; uint8_t reverse_active, indirect_active, indirect_ready; void* reverse_timer; uint64_t reverse_deadline_tb, indirect_deadline_tb; struct { void* timer; uint32_t request_id; void* conn_ctx; } main; struct CONN_MGR* mgr; }; struct CONN_MGR { struct UTUN_INSTANCE* instance; struct TOPO_GROUP* group; struct ll_queue* entries; void *bg_ping_timer, *candidate_ping_timer; void *bg_ping_wait, *candidate_ping_wait; /* standby_wait handle (Android) */ size_t bg_ping_cursor; uint64_t bg_ping_cycle_start_tb; struct CONN_MGR_CANDIDATE best_candidates[CONN_MGR_MAX_CANDIDATES]; uint8_t best_candidate_count; struct stcp_client* cand_tcp_pings[CONN_MGR_MAX_CANDIDATES]; /* влётные candidate TCP-пинги (для отмены при destroy) */ uint32_t next_request_id, direct_timeout_ms; uint8_t initialized; struct cm_reverse_pending* reverse_pending; struct cm_exchange_pending* exchange_pending; uint8_t _unused[0]; }; /* ═══════ декларации внутренних функций ═══════ */ /* core — публичные (в priv.h, не в conn_mgr.h) */ int cm_open(struct CONN_MGR* mgr, uint64_t node_id, conn_mgr_cb_t cb, void* cb_arg, struct CONN_MGR_HANDLE** out_handle); /* core */ struct CONN_MGR_ENTRY* cm_find_entry(struct CONN_MGR* mgr, uint64_t node_id); struct CONN_MGR_ENTRY* cm_ensure_entry(struct CONN_MGR* mgr, uint64_t node_id); void cm_entry_cleanup(struct CONN_MGR_ENTRY* entry); void cm_cleanup_db_node(struct CONN_MGR_ENTRY* entry); void cm_deliver_event(struct CONN_MGR_ENTRY* entry, enum conn_mgr_event event); void cm_update_nodeinfo(struct CONN_MGR_ENTRY* entry); void cm_clear_nodeinfo(struct CONN_MGR* mgr, uint64_t node_id); void cm_ncd_callback(struct NODE_CONN_DIRECT* ncd_h, enum ncd_event ncd_ev, void* arg); void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry); void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry); void cm_start_phase_indirect(struct CONN_MGR_ENTRY* entry); void cm_start_local_scan(struct CONN_MGR_ENTRY* entry); void cm_handle_direct_req(uint64_t src, struct CONN_MGR* mgr, const uint8_t* data, size_t len); void cm_handle_disconnect(struct CONN_MGR* mgr, uint64_t node_id); void cm_reverse_tick_cb(void* arg); void cm_finalize_indirect(struct CONN_MGR_ENTRY* entry); void cm_add_v4_link(struct ETCP_CONN* conn, const uint8_t* addr, uint16_t port, struct ETCP_SOCKET* s); void cm_add_v6_link(struct ETCP_CONN* conn, const uint8_t addr[16], uint16_t port, struct ETCP_SOCKET* s); int cm_has_direct_ip(struct CONN_MGR* mgr, struct TOPO_GROUP_NODE* nq); int cm_has_local_addr(struct CONN_MGR* mgr, struct TOPO_GROUP_NODE* nq); uint8_t cm_classify_v6_addr(const uint8_t addr[16]); uint8_t cm_sock_v6_classify(const struct ETCP_SOCKET* s); #define CM_V6_LL 0 #define CM_V6_LOC 1 #define CM_V6_DIR 2 #define CM_V6_OTH 3 #define CM_V6_ANY 4 /* indirect */ void cm_exchange_tick_cb(void* arg); void cm_compute_intermediaries(struct CONN_MGR_ENTRY* entry, struct CM_EXCHANGE_RESP* resp); void cm_exchange_probe_retry_cb(void* arg); void cm_handle_interm_exchange_req(uint64_t src, struct CONN_MGR* mgr, struct CM_EXCHANGE_REQ* req); void cm_handle_interm_exchange_resp(struct CONN_MGR* mgr, const uint8_t* data, size_t len); void cm_handle_interm_selected(struct CONN_MGR* mgr, uint64_t src, const uint8_t* data, size_t len); /* monitor */ void cm_bg_ping_timer_cb(void* arg); void cm_candidate_ping_timer_cb(void* arg); uint64_t cm_get_node_max_probe_time(struct TOPO_GROUP_NODE* nq); int cm_is_rtt_fresh(struct TOPO_GROUP_NODE* nq, uint64_t now_tb); #endif