#ifndef ETCP_CONNECTIONS_H #define ETCP_CONNECTIONS_H // подмодуль ETCP который обслуживает сокеты ETCP для приёма-передачи пакетов и одно ETCP подключение через несколько каналов связи (failover) #include "secure_channel.h" #include "utun_instance.h" #include "../lib/socket_compat.h" #include #define PACKET_DATA_SIZE 1600//1536 // Типы кодограмм протокола #define ETCP_INIT_REQUEST 0x02 #define ETCP_INIT_RESPONSE 0x03 #define ETCP_INIT_REQUEST_NOINIT 0x04 #define ETCP_INIT_RESPONSE_NOINIT 0x05 #pragma pack(push, 1) struct ETCP_DGRAM {// пакет (незашифрованный) struct ETCP_LINK* link;// откуда получена или куда отправялем uint16_t data_len;// общий размер пакета не включая timestamp uint16_t noencrypt_len;// число байт (с конца) которые не надо шифровать. для передачи pubkey uint16_t timestamp;// timestamp отправляющего узла при отправке пакета uint8_t flag_up:1;// bit0 = up/down (recv_keepalive) uint8_t data[0];// данные пакета (без timestamp) }; #pragma pack(pop) // список активных подключений которые обслуживает сокет. каждый сокет может обслуживать много подключений struct ETCP_SOCKET { struct ETCP_SOCKET* next; // Linked list для всех соединений struct UTUN_INSTANCE* instance; socket_t fd; // UDP socket (cross-platform) struct sockaddr_storage local_addr; // Локальный адрес int mtu; // MTU для этого сокета int loss_rate; // packet loss rate in percent (0-100) // для входящих подключений (links) - массив упорядоченный по ip_port_hash size_t max_channels; // сколько выделено памяти size_t num_channels; // сколько активно struct ETCP_LINK** links;// массив указателей на линки, сортированный по ip_port_hash int errorcode; size_t pkt_format_errors; void* socket_id; // Socket ID from uasync_add_socket uint8_t type; // CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE uint32_t local_defaultroute_ip; // auto-detected IPv4 for public servers (network byte order) }; // ETCP Link - одно динамическое соединение (один путь) struct ETCP_LINK { uint32_t ip_port_hash; // crc32 для быстрого поиска struct ETCP_LINK* next; // Linked list подключений для ETCP_CONN (каждое подключение это child для ETCP_CONN) struct ETCP_CONN* etcp; // подключение (parent) struct ETCP_SOCKET* conn; // сокет через который работаем // Путь соединения struct sockaddr_storage remote_addr; // Удалённый адрес // Параметры соединения uint16_t mtu; // MTU общий uint16_t mtu_local; // MTU моего зла uint16_t mtu_remote; // MTU удаленного узла uint16_t keepalive_interval; // Keepalive интервал (x1ms) uint32_t recovery_interval; // recovery интервал (x0.1ms) uint8_t is_server; // инициирует подключение клиент uint8_t initialized; // Флаг инициализации (1=подтверждено или получен request) uint8_t local_link_id; // id моего линка uint8_t remote_link_id; // id этого линка на peer (устанавливается в момент initialized) uint8_t recv_keepalive; // 1 - up, 0 - down (принимаются ли пакеты) uint8_t remote_keepalive; // 1 - up, 0 - down (удаленная сторона сообщает - принимаются ли у нее пакеты) uint8_t link_status; // 1 - up, 0 - down (итоговый статус - если есть проблемы на любой стороне - линк down) uint8_t link_state; // 0 - just init, 1 - handshake, 2 - try reconnect, 3 - connected // Состояние установки соединения (только для клиентов) void* init_timer; // Таймер для повторов INIT (NULL=не подключается) uint16_t init_timeout; // Текущий таймаут в мс uint16_t init_retry_count; // Счетчик попыток // uint64_t last_activity; // Время последней активности uint64_t last_recv_local_time; // x0.1 ms uint16_t last_recv_timestamp; uint8_t last_recv_updated; // =1 при обновлении timestamp, =0 при отправке (чтобы не дублировать отправки при отсутствии обновлений) uint64_t shaper_load_time_tb; // основной в 0.1 мс units uint64_t shaper_sub_nanotime; // sub 0-999999 для 0.1 нс - 0.1 мс uint8_t shaper_state; void* shaper_timer; uint32_t inflight_bytes; uint32_t inflight_packets; size_t encrypt_errors; size_t decrypt_errors; size_t send_errors; size_t recv_errors; size_t total_encrypted; size_t total_decrypted; uint16_t rtt_last; // round trip (время отправки + приёма) uint16_t rtt_history[10]; // Circular buffer for last 10 RTT values uint8_t rtt_history_count; // Number of valid entries in history (0-10) uint8_t rtt_history_index; // Current write position in history buffer uint32_t jitter; // Current jitter [>>16] x0.1 ms uint16_t rtt_max_val; // Current max RTT in history uint8_t rtt_max_idx; // Index of max (255 = needs recalc) uint16_t rtt_avg10; // round trip average (excl. max) uint32_t recv_dt_avg_tx; // дельта времени для отправленных пакетов (относительное время отправки) x256 uint32_t recv_dt_avg_rx; // дельта времени для принятых пакетов (относительное время отправки) x256 uint16_t tt_last; // transmit time (время доставки отправленных пакетов) uint16_t rt_last; // recv time (время доставки принятых пакетов) uint32_t bandwidth; // Link bandwidth in Kbits/sec // NAT address tracking (from INIT_RESPONSE) uint32_t nat_ip; // NAT IPv4 address (network byte order), 0 = not set uint16_t nat_port; // NAT port (network byte order) uint32_t nat_changes_count; // Counter of NAT address changes uint32_t nat_hits_count; // Counter of NAT address matches (new init response with same IP:port) // Keepalive state void* keepalive_timer; // Таймер для отправки keepalive пакетов uint32_t keepalive_timeout; // таймаут (ms) uint8_t pkt_sent_since_keepalive; // Флаг: был ли отправлен пакет с последнего keepalive тика uint32_t keepalive_sent_count; // Счётчик отправленных keepalive uint32_t keepalive_recv_count; // Счётчик полученных keepalive }; // INITIALIZATION (создаёт listen-сокеты и подключения из конфига) int init_connections(struct UTUN_INSTANCE* instance); // SOCKET FUNCTIONS // добавляет новый версер (сокет для приёма и отправки кодограмм. обслуживает много подключений) struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct sockaddr_storage* ip, uint32_t netif_index, int so_mark, uint8_t type, int mtu, int loss_rate); // удаляет сокет и освобождает ресурсы (грохает все его подключения и сокет) void etcp_socket_remove(struct ETCP_SOCKET* conn); // connection functions // создает новый канал связи для etcp подключения (ETCP_CONN) struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn, struct sockaddr_storage* remote_addr, uint8_t is_server); void etcp_link_close(struct ETCP_LINK* link); //int etcp_input_cbk(struct packet_buffer* pkt, struct ETCP_SOCKET* conn);// получает расшифрованный пакет int etcp_encrypt_send(struct ETCP_DGRAM* dgram);// зашифровывает и отправляет пакет // find link by address struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr); // find free local_link_id for connection // scans all links in connection, marks used ids in bit array // returns first free id (0-255) or -1 if all occupied int etcp_find_free_local_link_id(struct ETCP_CONN* etcp); #endif // ETCP_CONNECTIONS_H