100 lines
7.4 KiB
C
100 lines
7.4 KiB
C
/* Exit TCP-прокси: принимает CONNECT/DATA через UTUN-router и открывает обычный TCP к назначению.
|
|
* Поток определяется парой peer_node_id/stream_id; proxy_flow согласует окна и half-close.
|
|
* init учитывает tcp_proxy_server_enabled в конфиге; destroy закрывает потоки и общий UDP/ICMP-прокси.
|
|
* Сначала init, затем приём через router callback, в конце destroy; повторный init живого сервера недопустим.
|
|
* Состояние принадлежит UTUN_INSTANCE, операции и callbacks выполняются в его uasync-потоке.
|
|
* CLOSE дренирует запись и прекращает чтение; ERROR немедленно уничтожает поток, FIN — half-close. */
|
|
#ifndef TCP_PROXY_SERVER_H
|
|
#define TCP_PROXY_SERVER_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
#include <stdint.h>
|
|
#include "../lib/socket_compat.h"
|
|
#include "../lib/ll_queue.h"
|
|
#include "../lib/tcp_io.h"
|
|
#include "../routing_layer/etcp_router.h"
|
|
|
|
struct UTUN_INSTANCE;
|
|
struct UASYNC;
|
|
struct ll_entry;
|
|
struct ETCP_CONN;
|
|
|
|
#include "proxy_protocol.h"
|
|
|
|
struct tcp_proxy_server_conn {
|
|
struct tcp_proxy_server_conn* next; // следующий поток exit
|
|
struct tcp_proxy_server* ctx; // заимствованный владелец в inst
|
|
struct tcp_conn* tc; // собственный OS TCP к назначению
|
|
struct proxy_flow flow; // окно, FIN и control retry
|
|
uint32_t stream_id; // ID клиента; уникален в паре с peer_node_id
|
|
uint64_t peer_node_id; // конечный ingress-узел, не транспортный сосед
|
|
uint8_t dest_ip[4]; // IPv4 назначения в сетевом порядке
|
|
uint16_t dest_port; // порт назначения в сетевом порядке
|
|
|
|
uint8_t close_queued; // close-маркер уже поставлен в write_queue TCP
|
|
uint8_t cli_closed; // client sent CLOSE
|
|
|
|
void* diag_timer; // 1-секундный таймер диагностики
|
|
uint8_t freed; // логически удалён; сама структура освобождается через call_soon
|
|
|
|
struct queue_waiter_handle pause_waiter; // ожидание свободного места в router send_q
|
|
void* retry_timer; // fallback 500 мс: возобновить read_queue, DATA отправляется с force=0
|
|
uint32_t bytes_sent; // сумма входящих DATA, учитывается до проверки/записи в TCP
|
|
uint32_t bytes_relayed; // байт принято router для клиента
|
|
uint32_t drain_count; // число успешно отправленных DATA из read_queue
|
|
uint32_t data_count; // счётчик входящих DATA от клиента
|
|
struct UASYNC* ua; // заимствованный loop для таймеров и отложенного free
|
|
};
|
|
|
|
struct tcp_proxy_server {
|
|
int enabled; // exit обслуживает CONNECT/UDP/ICMP REQUEST
|
|
int conn_count; // число потоков в conns
|
|
struct tcp_proxy_server_conn* conns; // собственные потоки всех пиров
|
|
struct UTUN_INSTANCE* inst; // заимствованный instance, содержащий сервер
|
|
};
|
|
|
|
// Обнулить состояние и учесть config->global.tcp_proxy_server_enabled; NULL inst → -1, иначе 0.
|
|
// Без конфига/при отключении не bind-ит сервис. При включении bind SERVER и вызывает UDP/ICMP init.
|
|
// 0 не гарантирует успешный bind/UDP/ICMP: их ошибки не пробрасываются вызывающему коду.
|
|
int tcp_proxy_server_init(struct UTUN_INSTANCE* inst);
|
|
// Удалить потоки, выключить сервер, снять binding и уничтожить общие UDP/ICMP; NULL inst допустим.
|
|
// Перед этим остановить tcp_proxy_client того же inst; дать ua обработать отложенные освобождения.
|
|
void tcp_proxy_server_destroy(struct UTUN_INSTANCE* inst);
|
|
|
|
// Линейный поиск в ненулевом ctx по паре peer/sid; заимствованный указатель или NULL.
|
|
struct tcp_proxy_server_conn* tcp_proxy_server_find_conn(struct tcp_proxy_server* ctx, uint64_t peer, uint32_t stream_id);
|
|
// Немедленно удалить rc из списка, закрыть TCP и отменить таймеры/waiter; NULL допустим.
|
|
// Память rc освобождается отложенно в ua; сама функция не отправляет CLOSE/ERROR пиру.
|
|
void tcp_proxy_server_conn_free(struct tcp_proxy_server_conn* rc);
|
|
|
|
// Router callback: conn->instance — владелец, peer берётся из ROUTER_SVC_SRC_OFF entry.
|
|
// Принимает владение entry/dgram при любом исходе. Пустой payload router удаляет потоки этого peer.
|
|
void tcp_proxy_server_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry);
|
|
|
|
// entry — полный приёмный пакет CONNECT с IPv4/портом; принимает владение entry/dgram.
|
|
// inst должен быть включён, sid/src — уже разобранные поля. 0 = connect запущен/готов, -1 = ошибка.
|
|
// CONNECTED отправляется только после реального connect; таймаут — из connect_timeout_ms (0 = отключён).
|
|
int tcp_proxy_server_handle_connect(struct UTUN_INSTANCE* inst, struct ll_entry* entry,
|
|
uint32_t stream_id, uint64_t src_node_id);
|
|
// Полный entry DATA не короче RECV_HDR_SIZE; принимает владение entry/dgram. conn сейчас не используется.
|
|
// Peer берётся из entry; проверяет окно и ставит данные в OS write_queue. 0 = обработано, -1 = отклонено.
|
|
// Ошибка выделения в write_queue может закрыть поток и при возврате 0: это не подтверждение OS send.
|
|
int tcp_proxy_server_handle_data(struct UTUN_INSTANCE* inst, struct ETCP_CONN* conn, struct ll_entry* entry, uint32_t stream_id);
|
|
// CLOSE: прекратить чтение, отбросить read_queue и закрыть TCP после записи уже принятой write_queue.
|
|
void tcp_proxy_server_handle_close(struct UTUN_INSTANCE* inst, uint64_t peer, uint32_t stream_id);
|
|
// ERROR: немедленно удалить поток вместе с непрочитанными/незаписанными данными.
|
|
void tcp_proxy_server_handle_error(struct UTUN_INSTANCE* inst, uint64_t peer, uint32_t stream_id);
|
|
// FIN: поставить shutdown(SHUT_WR) после уже принятых DATA; обратное направление продолжает работать.
|
|
// handle_close/error/fin допускают NULL inst и отсутствующую пару peer/sid.
|
|
void tcp_proxy_server_handle_fin(struct UTUN_INSTANCE* inst, uint64_t peer, uint32_t stream_id);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|