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.
278 lines
10 KiB
278 lines
10 KiB
/** |
|
* @file topo_node.h |
|
* @brief Модель данных узла сети — структуры, сериализация, wire-формат. |
|
* |
|
* Этот модуль определяет: |
|
* - Как узел представлен в памяти (TOPO_NODE, TOPO_NODEQ, адреса, подсети) |
|
* - Как узел передаётся по сети (packed-структуры TOPOMSG_*) |
|
* - Как узел сериализуется/десериализуется (topo_node_serialize/deserialize) |
|
* |
|
* Модуль не содержит сетевой логики и BGP-обмена — этим занимается topo_group. |
|
* |
|
* Хранение: данные узлов сохраняются в SQLite (таблицы nodes, node_addresses) |
|
* через модуль topo_node_sqlite. |
|
* |
|
* Основные понятия: |
|
* TOPO_NODE — идентичность узла (pubkeys, имя, версия, списки адресов) |
|
* TOPO_NODEQ — запись в очереди группы (плюс пути, hop_list, связность) |
|
* TOPO_NODEPATH — путь до узла через конкретное ETCP-соединение |
|
* TOPOMSG_NODE — wire-формат, передаваемый по NODEINFO |
|
*/ |
|
#ifndef TOPO_NODE_H |
|
#define TOPO_NODE_H |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
#include <stdint.h> |
|
#include <stddef.h> |
|
#include "../lib/ll_queue.h" |
|
#include "secure_channel.h" |
|
|
|
struct TOPO_GROUP; |
|
struct ETCP_SOCKET; |
|
struct UTUN_INSTANCE; |
|
|
|
// ---- типы адресов в плоском списке TOPOMSG_ADDR4 ---- |
|
|
|
#define TOPO_ADDR_INTERFACE 0 // interface_addr сокета (LAN) |
|
#define TOPO_ADDR_NAT 1 // nat_addr после детекции NAT |
|
#define TOPO_ADDR_REAL 2 // подтверждённый прямой интернет-адрес (nat проверка показала совпадение с interface_addr) |
|
|
|
// ---- протоколы транспорта (поле protocol в TOPOMSG_ADDR4/TOPOMSG_ADDR6) ---- |
|
#define TOPO_PROTO_UDP 0x01 |
|
#define TOPO_PROTO_TCP 0x02 |
|
|
|
// ---- типы NAT (etcp_connections.h) ---- |
|
// NAT_TYPE_UNKNOWN(0), NAT_TYPE_EIM(1), NAT_TYPE_STRICT(2) |
|
// NAT_VERIFIED_UNKNOWN(4), NAT_VERIFIED_EIM(5), NAT_VERIFIED_STRICT(6), NAT_VERIFIED_DIRECT(7) |
|
|
|
// ---- типы адресов для БД (node_addresses.addr_type) ---- |
|
#define ADDR_TYPE_NETIF 0 // interface / auto-detected |
|
#define ADDR_TYPE_DIRECT 1 // прямой публичный адрес (detected no NAT) |
|
#define ADDR_TYPE_NAT_EIM 2 // EIM NAT |
|
#define ADDR_TYPE_NAT_STRICT 3 // strict NAT |
|
|
|
// ---- статусы зондирования связности ---- |
|
|
|
#define PROBE_STATUS_NONE 0 |
|
#define PROBE_STATUS_IN_PROGRESS 1 |
|
#define PROBE_STATUS_DONE 2 |
|
|
|
#define PROBE_RESULT_UNKNOWN 0 |
|
#define PROBE_RESULT_REACHABLE 1 |
|
#define PROBE_RESULT_UNREACHABLE 2 |
|
|
|
#define CONN_PROBE_COUNT 3 |
|
#define CONN_PROBE_TIMEOUT_MS 1000 |
|
|
|
#define CONN_TYPE_NONE 0 |
|
#define CONN_TYPE_DIRECT 1 |
|
#define CONN_TYPE_REVERSE 2 |
|
#define CONN_TYPE_INDIRECT 3 |
|
#define CONN_MGR_MAX_INTERMEDIARIES 3 |
|
|
|
// ---- флаги nodeinfo ---- |
|
#define TOPO_FLAG_SEND_SUBNETS 0x01 |
|
|
|
// ---- group_id по умолчанию ---- |
|
#define TOPO_GROUP_UTUN 0x8000000000000000ULL |
|
|
|
// ---- типы групп ---- |
|
#define TOPO_GROUP_TYPE_UTUN 1 |
|
#define TOPO_GROUP_TYPE_CHAT 2 |
|
|
|
// ---- состояние связности с удалённым узлом (локальное, не передаётся по BGP) ---- |
|
|
|
struct TOPO_CONNECTIVITY { |
|
uint8_t probe_status; |
|
uint8_t pending_count; |
|
uint64_t probe_start_time; |
|
uint16_t interface_min_rtt; |
|
uint16_t nat_min_rtt; |
|
uint16_t real_min_rtt; |
|
uint8_t interface_status; |
|
uint8_t nat_status; |
|
uint8_t real_status; |
|
uint8_t reserved; |
|
uint64_t interface_probe_time; |
|
uint64_t nat_probe_time; |
|
uint64_t real_probe_time; |
|
uint64_t ping_req_time; |
|
void* probe_list; |
|
}; |
|
|
|
// ======================================================================= |
|
// Протокольные структуры (wire-format, packed, без next) |
|
// ======================================================================= |
|
|
|
struct TOPOMSG_SOCKMETA4 { |
|
uint8_t id; |
|
uint8_t config_type; |
|
uint8_t nat_type; |
|
} __attribute__((packed)); |
|
|
|
struct TOPOMSG_ADDR4 { |
|
uint8_t addr[4]; |
|
uint16_t port; |
|
uint8_t type; |
|
uint8_t socket_id; |
|
uint8_t protocol; |
|
} __attribute__((packed)); |
|
|
|
struct TOPOMSG_SOCKMETA6 { |
|
uint8_t id; |
|
uint8_t config_type; |
|
uint8_t nat_type; |
|
} __attribute__((packed)); |
|
|
|
struct TOPOMSG_ADDR6 { |
|
uint8_t addr[16]; |
|
uint16_t port; |
|
uint8_t type; |
|
uint8_t socket_id; |
|
uint8_t protocol; |
|
} __attribute__((packed)); |
|
|
|
struct TOPOMSG_SUBNET4 { |
|
uint8_t addr[4]; |
|
uint8_t prefix_length; |
|
} __attribute__((packed)); |
|
|
|
struct TOPOMSG_SUBNET6 { |
|
uint8_t addr[16]; |
|
uint8_t prefix_length; |
|
} __attribute__((packed)); |
|
|
|
struct TOPOMSG_TRANZIT { |
|
uint64_t node_id; |
|
uint16_t rtt; |
|
uint16_t link_q; |
|
} __attribute__((packed)); |
|
|
|
/** |
|
* @brief Протокольный формат NODEINFO сообщения (wire-format) |
|
*/ |
|
struct TOPOMSG_NODE { |
|
uint8_t flags; |
|
uint64_t group_id; |
|
uint64_t node_id; |
|
uint8_t ver; |
|
uint8_t public_key[SC_PUBKEY_SIZE]; |
|
uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; |
|
uint8_t node_name_len; |
|
uint8_t local_v4_sockets; |
|
uint8_t local_v4_addrs; |
|
uint8_t local_v6_sockets; |
|
uint8_t local_v6_addrs; |
|
uint8_t local_v4_subnets; |
|
uint8_t local_v6_subnets; |
|
uint8_t tranzit_nodes; |
|
uint8_t hop_count; |
|
} __attribute__((packed)); |
|
|
|
#define TOPOMSG_NODE_HDR_SIZE sizeof(struct TOPOMSG_NODE) |
|
|
|
// ======================================================================= |
|
// Структуры для хранения в памяти (linked list с next* первым полем) |
|
// ======================================================================= |
|
|
|
struct TOPO_SOCKMETA4 { struct TOPO_SOCKMETA4* next; uint8_t id, config_type, nat_type; }; |
|
struct TOPO_ADDR4 { struct TOPO_ADDR4* next; uint8_t addr[4]; uint16_t port; uint8_t type, socket_id, protocol; }; |
|
struct TOPO_SOCKMETA6 { struct TOPO_SOCKMETA6* next; uint8_t id, config_type, nat_type; }; |
|
struct TOPO_ADDR6 { struct TOPO_ADDR6* next; uint8_t addr[16]; uint16_t port; uint8_t type, socket_id, protocol; }; |
|
struct TOPO_SUBNET4 { struct TOPO_SUBNET4* next; uint8_t addr[4]; uint8_t prefix_length; }; |
|
struct TOPO_SUBNET6 { struct TOPO_SUBNET6* next; uint8_t addr[16]; uint8_t prefix_length; }; |
|
|
|
// Универсальная голова списка (next — первое поле во всех TOPO_*) |
|
struct _topo_head { struct _topo_head* next; }; |
|
|
|
static inline int topo_list_count(struct _topo_head* head) { int n = 0; while (head) { n++; head = head->next; } return n; } |
|
|
|
/** |
|
* @brief Идентификационная информация об узле (память, разделяется между группами) |
|
*/ |
|
struct TOPO_NODE { |
|
uint32_t ref_count; |
|
uint8_t flags; |
|
uint64_t group_id; |
|
uint64_t node_id; |
|
uint8_t ver; |
|
uint8_t public_key[SC_PUBKEY_SIZE]; |
|
uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; |
|
char* node_name; // отдельный u_strdup/u_free |
|
struct TOPO_SOCKMETA4* v4_sock_meta; // linked list head |
|
struct TOPO_ADDR4* v4_addrs; // linked list head |
|
struct TOPO_SOCKMETA6* v6_sock_meta; |
|
struct TOPO_ADDR6* v6_addrs; |
|
}; |
|
|
|
/** |
|
* @brief Подсети узла (отдельный malloc, NULL если нет подсетей) |
|
*/ |
|
struct TOPO_NODESUBNETS { |
|
struct TOPO_SUBNET4* v4_subnets; // linked list head |
|
struct TOPO_SUBNET6* v6_subnets; |
|
}; |
|
|
|
struct TOPO_NODEPATH { |
|
struct ll_entry ll; |
|
struct ETCP_CONN* conn; |
|
uint8_t hop_count; |
|
}; |
|
|
|
struct TOPO_NODEQ { |
|
struct ll_entry ll; |
|
uint64_t hash_node_id; // копия node_id для хеш-индекса |
|
struct TOPO_NODE* node; // отдельный malloc, ref_count |
|
struct TOPO_NODESUBNETS* subnets; // отдельный malloc (NULL если без подсетей) |
|
struct TOPOMSG_TRANZIT* tranzit_data; // отдельный malloc |
|
uint64_t* hop_list; // отдельный malloc |
|
uint8_t tranzit_count; |
|
uint8_t hop_count; |
|
struct ll_queue* paths; |
|
uint8_t dirty; |
|
uint8_t last_ver; |
|
uint8_t alien; |
|
uint8_t conn_mgr_type; |
|
uint64_t conn_mgr_intermediaries[CONN_MGR_MAX_INTERMEDIARIES]; |
|
uint8_t conn_mgr_intermediariy_count; |
|
struct TOPO_CONNECTIVITY connectivity; |
|
struct ETCP_SOCKET* best_socket; |
|
}; |
|
|
|
|
|
// ======================================================================= |
|
// API |
|
// ======================================================================= |
|
|
|
struct TOPO_NODEQ* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_id); |
|
|
|
void topo_node_ref(struct TOPO_NODE* ni); |
|
void topo_node_unref(struct TOPO_NODE* ni); |
|
void topo_node_free_lists(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq); |
|
int topo_node_dyn_size(const struct TOPOMSG_NODE* msg); |
|
|
|
// convenience accessors |
|
static inline const struct TOPO_SOCKMETA4* topo_v4_sock_meta(const struct TOPO_NODE* ni) { return ni->v4_sock_meta; } |
|
static inline const struct TOPO_ADDR4* topo_v4_addrs(const struct TOPO_NODE* ni) { return ni->v4_addrs; } |
|
static inline const struct TOPO_SOCKMETA6* topo_v6_sock_meta(const struct TOPO_NODE* ni) { return ni->v6_sock_meta; } |
|
static inline const struct TOPO_ADDR6* topo_v6_addrs(const struct TOPO_NODE* ni) { return ni->v6_addrs; } |
|
static inline const struct TOPO_SUBNET4* topo_v4_subnets(const struct TOPO_NODESUBNETS* r) { return r ? r->v4_subnets : NULL; } |
|
static inline const struct TOPO_SUBNET6* topo_v6_subnets(const struct TOPO_NODESUBNETS* r) { return r ? r->v6_subnets : NULL; } |
|
|
|
int topo_node_serialize(struct TOPO_GROUP* group, struct TOPO_NODEQ* nq, uint8_t* out, size_t out_max); |
|
int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets, |
|
struct TOPOMSG_TRANZIT** out_tranzit, uint8_t* out_tranzit_count, uint64_t** out_hop_list, uint8_t* out_hop_count); |
|
|
|
int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* group); |
|
|
|
void topo_node_dump_all(struct TOPO_GROUP* group); |
|
int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size); |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
#endif // TOPO_NODE_H
|
|
|