You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

181 lines
7.9 KiB

#ifndef CONN_MGR_PRIV_H
#define CONN_MGR_PRIV_H
#include "conn_mgr.h"
#include <stdint.h>
#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