- platform_compat: get_interface_ip_by_index() для получения IP по ifindex - ETCP_SOCKET: interface_addr заполняется из конфига/interface/default route - BGP_NAT_CHECK_REQ: добавлены interface_ip/interface_port (network byte order) - route_bgp_send_nat_check_req: отправляет interface_addr линка - route_bgp_handle_nat_check_req: принимает interface данные в sockaddr-заглушку
220 lines
11 KiB
Plaintext
220 lines
11 KiB
Plaintext
Диаграмма вызовов функций при определении типа NAT (NAT detection)
|
||
=====================================================================
|
||
|
||
=== ИНИЦИАЛИЗАЦИЯ BGP ===
|
||
|
||
route_bgp_init(instance)
|
||
└── etcp_set_new_conn_cbk(instance, route_bgp_etcp_conn_cbk, NULL)
|
||
└── При создании нового ETCP_CONN:
|
||
route_bgp_etcp_conn_cbk(conn, arg)
|
||
├── etcp_conn_set_up_cbk(conn, route_bgp_on_conn_up, bgp)
|
||
└── etcp_conn_set_down_cbk(conn, route_bgp_on_conn_down, bgp)
|
||
|
||
|
||
=== УСТАНОВКА СОЕДИНЕНИЯ (сервер получает INIT_REQUEST) ===
|
||
|
||
etcp_connections_read_callback_socket(sock, arg)
|
||
└── Получает ETCP_INIT_REQUEST
|
||
├── etcp_connection_create(instance, name) [если новый peer]
|
||
│ └── Вызывает instance->etcp_new_conn_cbk [route_bgp_etcp_conn_cbk]
|
||
├── etcp_link_new(etcp, e_sock, remote_addr, is_server=1)
|
||
├── Отправляет ETCP_INIT_RESPONSE (с NAT info)
|
||
├── link->initialized = 1
|
||
└── etcp_conn_ready(link->etcp)
|
||
└── conn->ready_cbk
|
||
└── etcp_on_up(etcp)
|
||
└── etcp->up_cbk = route_bgp_on_conn_up(etcp, bgp)
|
||
|
||
|
||
=== УСТАНОВКА СОЕДИНЕНИЯ (клиент получает INIT_RESPONSE) ===
|
||
|
||
etcp_connections_read_callback_socket(sock, arg)
|
||
└── Получает ETCP_INIT_RESPONSE
|
||
├── Сохраняет NAT address: link->nat_ip, link->nat_port
|
||
├── link->initialized = 1
|
||
└── etcp_conn_ready(link->etcp)
|
||
└── etcp_on_up(etcp)
|
||
└── etcp->up_cbk = route_bgp_on_conn_up(etcp, bgp)
|
||
|
||
|
||
=== ЗАПУСК ПРОВЕРКИ NAT (при поднятии соединения) ===
|
||
|
||
route_bgp_on_conn_up(etcp, arg)
|
||
└── route_bgp_new_conn(conn)
|
||
├── route_bgp_add_to_senders(bgp, conn)
|
||
└── Сканирует ВСЕ линки ВСЕХ соединений:
|
||
if (link->initialized && link->conn && link->nat_check_status < NAT_CHECK_IN_PROGRESS)
|
||
└── route_bgp_start_link_nat_check(bgp, link)
|
||
├── if (nat_check_status == IN_PROGRESS) return
|
||
├── route_bgp_find_third_node(bgp, exclude=link->etcp)
|
||
│ └── Ищет другой ETCP_CONN в senders_list
|
||
├── Определяет target_ip/target_port:
|
||
│ ├── Если link->nat_ip != 0: использует nat_ip/nat_port
|
||
│ └── Иначе: использует link->remote_addr
|
||
├── Проверяет is_local_subnet(target_ip) [если запрещено - skip]
|
||
├── route_bgp_extract_nat_addr(conn, &nat_ip, &nat_port)
|
||
│ └── Ищет первый линк с nat_ip != 0
|
||
├── Создает nat_check_arg { link, nat_ip, nat_port }
|
||
└── route_ping_send_req_addr(bgp, third_conn, target_ip, target_port,
|
||
count=3, interval=500ms, timeout=1000ms,
|
||
wait_timeout=5000ms,
|
||
cb=nat_link_check_cb, arg=nat_check_arg,
|
||
pubkey=peer_pubkey)
|
||
|
||
|
||
=== ОТПРАВКА ЗАПРОСА НА ПИНГ (через third node) ===
|
||
|
||
route_ping_send_req_addr(bgp, to_conn, target_ip, target_port, ...)
|
||
├── Создает BGP_PING_REQUEST { cmd, subcmd=PING_REQ, request_id, count, interval, timeout, target_ipv4, target_port, pubkey }
|
||
├── etcp_send(to_conn, entry) [отправляет запрос third node]
|
||
├── Создает route_ping_pending { request_id, callback=nat_link_check_cb, arg, timeout_timer }
|
||
└── Добавляет в bgp->ping_pending
|
||
|
||
|
||
=== ОБРАБОТКА PING_REQ (на third node) ===
|
||
|
||
route_bgp_receive_cbk(data, len, from_conn, bgp)
|
||
└── ROUTE_SUBCMD_PING_REQ
|
||
└── route_ping_handle_req(bgp, from_conn, data, len)
|
||
├── Создает route_ping_series_ctx { reply_conn, request_id, target_addr, pubkey, local_sock, count_total }
|
||
├── Находит первый IPv4 ETCP_SOCKET -> local_sock
|
||
└── etcp_send_ping_to_socket(instance, local_sock, pubkey, &target_addr,
|
||
timeout_ms, route_ping_single_cb, ctx, NULL, 0)
|
||
└── Отправляет ETCP пинг на target_addr
|
||
|
||
|
||
=== ОТВЕТ НА ПИНГ (целевой узел) ===
|
||
|
||
etcp_connections_read_callback_socket()
|
||
└── Получает ETCP пинг -> отправляет pong
|
||
|
||
|
||
=== ПОЛУЧЕНИЕ ОТВЕТА НА ПИНГ (third node) ===
|
||
|
||
route_ping_single_cb(success, rtt, arg, nonce, resp_data, resp_data_len)
|
||
├── Обновляет статистику: count_sent++, count_ok++, sum_rtt += rtt
|
||
├── Если count_sent < count_total:
|
||
│ └── etcp_send_ping_to_socket(...) [следующий пинг]
|
||
└── Иначе:
|
||
└── route_ping_series_finish(ctx)
|
||
├── Вычисляет avg_rtt
|
||
└── Создает BGP_PING_RESPONSE { cmd, subcmd=PING_RESP, request_id, count_sent, count_ok, avg_rtt }
|
||
└── etcp_send(reply_conn, entry) [отправляет результат инициатору]
|
||
|
||
|
||
=== ПОЛУЧЕНИЕ PING_RESP (на инициаторе) ===
|
||
|
||
route_bgp_receive_cbk(data, len, from_conn, bgp)
|
||
└── ROUTE_SUBCMD_PING_RESP
|
||
└── route_ping_handle_resp(bgp, from_conn, data, len)
|
||
├── Ищет route_ping_pending по request_id
|
||
├── Отменяет timeout_timer
|
||
└── Вызывает callback: nat_link_check_cb(success, avg_rtt, count_sent, count_ok, arg)
|
||
|
||
|
||
=== CALLBACK ПРОВЕРКИ NAT ===
|
||
|
||
nat_link_check_cb(success, avg_rtt, count_sent, count_ok, arg)
|
||
├── Определяет nat_type = success ? NAT_TYPE_OPEN : NAT_TYPE_RESTRICTED
|
||
├── link->nat_type = nat_type
|
||
├── link->nat_check_status = success ? NAT_CHECK_OPEN : NAT_CHECK_RESTRICTED
|
||
└── route_bgp_send_nat_info(link->etcp, socket_id, nat_ip, nat_port, nat_type)
|
||
├── Создает BGP_NAT_INFO { cmd, subcmd=NAT_INFO, socket_id, nat_ip[4], nat_port, nat_type }
|
||
└── etcp_send(conn, entry) [отправляет результат клиенту]
|
||
|
||
|
||
=== ПРИЕМ NAT_INFO (на клиенте) ===
|
||
|
||
route_bgp_receive_cbk(data, len, from_conn, bgp)
|
||
└── ROUTE_SUBCMD_NAT_INFO
|
||
└── route_bgp_handle_nat_info(bgp, from_conn, data, len)
|
||
├── Ищет линки по remote_socket_id
|
||
├── Устанавливает link->nat_type = info->nat_type
|
||
└── Логирует результат NAT detection
|
||
|
||
|
||
=== ЗАПРОС НА ПРОВЕРКУ NAT (NAT_CHECK_REQ - новый механизм) ===
|
||
|
||
route_bgp_send_nat_check_req(conn, socket_id)
|
||
├── Создает BGP_NAT_CHECK_REQ { cmd, subcmd=NAT_CHECK_REQ, socket_id, interface_ip, interface_port }
|
||
│ ├── Ищет линк с remote_socket_id == socket_id
|
||
│ └── Берет interface_addr из линка -> interface_ip/interface_port
|
||
└── etcp_send(conn, entry)
|
||
|
||
route_bgp_handle_nat_check_req(bgp, from_conn, data, len)
|
||
├── Принимает BGP_NAT_CHECK_REQ
|
||
├── Сохраняет interface_ip/interface_port в struct sockaddr_storage dummy
|
||
├── Ищет линк с remote_socket_id == req->socket_id
|
||
└── Если линк найден и не в процессе проверки:
|
||
└── route_bgp_start_link_nat_check(bgp, target_link)
|
||
[далее по стандартному flow]
|
||
|
||
|
||
=== СВЯЗЬ СТРУКТУР ===
|
||
|
||
struct ETCP_SOCKET
|
||
├── local_addr [адрес бинда из конфига]
|
||
├── interface_addr [IP интерфейса + порт: интерфейс/default route/конфиг]
|
||
└── ...
|
||
|
||
struct ETCP_LINK
|
||
├── remote_addr [адрес удаленного узла]
|
||
├── nat_ip [NAT IP, полученный из INIT_RESPONSE]
|
||
├── nat_port [NAT port, полученный из INIT_RESPONSE]
|
||
├── nat_type [OPEN/RESTRICTED, результат проверки]
|
||
├── nat_check_status [NONE/WAITING/IN_PROGRESS/OPEN/RESTRICTED]
|
||
├── initialized [0/1, флаг завершения handshake]
|
||
└── ...
|
||
|
||
struct ETCP_CONN
|
||
├── links [список ETCP_LINK]
|
||
├── up_cbk [route_bgp_on_conn_up]
|
||
├── down_cbk [route_bgp_on_conn_down]
|
||
├── ready_cbk [вызывается при etcp_conn_ready]
|
||
├── initialized [0/1, флаг готовности]
|
||
├── links_up [0/1, есть ли активные линки]
|
||
└── ...
|
||
|
||
|
||
=== СТАТУСЫ NAT CHECK ===
|
||
|
||
NAT_CHECK_NONE = 0 [не проверялся]
|
||
NAT_CHECK_WAITING = 1 [ожидает]
|
||
NAT_CHECK_IN_PROGRESS = 2 [проверка запущена]
|
||
NAT_CHECK_OPEN = 3 [результат: OPEN]
|
||
NAT_CHECK_RESTRICTED = 4 [результат: RESTRICTED]
|
||
|
||
NAT_TYPE_UNKNOWN = 0
|
||
NAT_TYPE_OPEN = 1
|
||
NAT_TYPE_RESTRICTED = 2
|
||
|
||
NAT_VERIFIED_UNKNOWN = 4
|
||
NAT_VERIFIED_OPEN = 5
|
||
NAT_VERIFIED_RESTRICTED = 6
|
||
NAT_VERIFIED_DIRECT = 7
|
||
|
||
|
||
=== СООБЩЕНИЯ ПРОТОКОЛА ===
|
||
|
||
ETCP_INIT_REQUEST (0x02) [клиент -> сервер]
|
||
ETCP_INIT_RESPONSE (0x03) [сервер -> клиент, включает NAT info]
|
||
ETCP_INIT_REQUEST_NOINIT (0x04)
|
||
ETCP_INIT_RESPONSE_NOINIT (0x05)
|
||
ETCP_PING (0x06)
|
||
ETCP_PONG (0x07)
|
||
|
||
ROUTE_SUBCMD_NODEINFO (0x04)
|
||
ROUTE_SUBCMD_REQUEST_TABLE (0x05)
|
||
ROUTE_SUBCMD_WITHDRAW (0x06)
|
||
ROUTE_SUBCMD_PING_REQ (0x07)
|
||
ROUTE_SUBCMD_PING_RESP (0x08)
|
||
ROUTE_SUBCMD_NAT_INFO (0x09)
|
||
ROUTE_SUBCMD_NAT_CHECK_REQ (0x0A)
|
||
|
||
|
||
=== ПОЛНЫЙ FLOW (одна строка) ===
|
||
|
||
Handshake: etcp_connections_read_callback_socket -> INIT_REQUEST/RESPONSE -> link->initialized=1 -> etcp_conn_ready -> etcp_on_up -> route_bgp_on_conn_up -> route_bgp_new_conn -> route_bgp_start_link_nat_check -> route_ping_send_req_addr -> (через ETCP) -> route_ping_handle_req -> etcp_send_ping_to_socket -> (UDP) -> route_ping_single_cb -> route_ping_series_finish -> route_ping_handle_resp -> nat_link_check_cb -> route_bgp_send_nat_info -> route_bgp_handle_nat_info
|
||
|
||
NAT_CHECK_REQ flow: route_bgp_send_nat_check_req -> BGP_NAT_CHECK_REQ -> route_bgp_handle_nat_check_req -> route_bgp_start_link_nat_check -> [стандартный ping flow]
|