Make TCP proxy construction atomic and retain instance datagrams
This commit is contained in:
1 parent
99be040488
commit
50da7fe457
3 files changed
+41
-25
No files matched your search
@@ -723,7 +723,8 @@ void tcp_proxy_client_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* en
|
||||
if (subcmd == TCP_PROXY_SUBCMD_ERROR) { tcp_proxy_client_handle_error(proxy, stream_id); queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
if (subcmd == TCP_PROXY_SUBCMD_FIN) { tcp_proxy_client_handle_fin(proxy, stream_id); queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
}
|
||||
if (subcmd == TCP_PROXY_SUBCMD_DATA || subcmd == TCP_PROXY_SUBCMD_CLOSE || subcmd == TCP_PROXY_SUBCMD_FIN || subcmd == TCP_PROXY_SUBCMD_ERROR) {
|
||||
if (subcmd == TCP_PROXY_SUBCMD_DATA || subcmd == TCP_PROXY_SUBCMD_CLOSE || subcmd == TCP_PROXY_SUBCMD_FIN ||
|
||||
subcmd == TCP_PROXY_SUBCMD_ERROR || subcmd == TCP_PROXY_SUBCMD_WINDOW) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_PROXY, "PROXY subcmd=%02x sid=%08x — client conn not found, silent drop", subcmd, stream_id);
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return;
|
||||
}
|
||||
@@ -742,6 +743,13 @@ struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, str
|
||||
int http_proxy_enabled, const char* http_proxy_addr)
|
||||
{
|
||||
if (!ua) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "ua is NULL"); return NULL; }
|
||||
if (inst && (inst->tcp_proxy_client || inst->router_bindings.callbacks[ETCP_RT_ID_TCP_PROXY_CLIENT])) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: duplicate instance binding"); return NULL;
|
||||
}
|
||||
if ((socks_enabled && (!socks_addr || !socks_addr[0])) ||
|
||||
(http_proxy_enabled && (!http_proxy_addr || !http_proxy_addr[0])) || mapping_count < 0 || (mapping_count && !mappings)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: missing listener address or invalid mappings"); return NULL;
|
||||
}
|
||||
|
||||
int need_tun = tun_name && tun_name[0] && tun_ip && tun_ip[0];
|
||||
if (!need_tun && !socks_enabled && !http_proxy_enabled) {
|
||||
@@ -787,21 +795,28 @@ struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, str
|
||||
if (socks_enabled && socks_addr && socks_addr[0]) {
|
||||
p->socks_listen = socks_proxy_init_listen(ua, socks_addr, &p->socks_conns, &p->socks_conn_count,
|
||||
&p->next_stream_id, inst, via_node_id, 0);
|
||||
if (!p->socks_listen) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "tcp_proxy_client: SOCKS init failed on %s", socks_addr); }
|
||||
if (!p->socks_listen) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "tcp_proxy_client: SOCKS init failed on %s", socks_addr);
|
||||
tcp_proxy_client_destroy(p); return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (http_proxy_enabled && http_proxy_addr && http_proxy_addr[0]) {
|
||||
p->http_listen = socks_proxy_init_listen(ua, http_proxy_addr, &p->http_conns, &p->http_conn_count,
|
||||
&p->next_stream_id, inst, via_node_id, 1);
|
||||
if (!p->http_listen) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "tcp_proxy_client: HTTP proxy init failed on %s", http_proxy_addr); }
|
||||
if (!p->http_listen) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "tcp_proxy_client: HTTP proxy init failed on %s", http_proxy_addr);
|
||||
tcp_proxy_client_destroy(p); return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (inst) {
|
||||
if (etcp_router_bind(inst, ETCP_RT_ID_TCP_PROXY_CLIENT, tcp_proxy_client_router_recv_cb) != 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_PROXY, "TCP proxy client: etcp_router_bind failed");
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: etcp_router_bind failed");
|
||||
tcp_proxy_client_destroy(p); return NULL;
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "TCP proxy client: etcp_router bind registered for ID=0x%02x", ETCP_RT_ID_TCP_PROXY_CLIENT);
|
||||
if (need_tun) { udp_proxy_init(inst, ua); icmp_proxy_init(inst, ua); }
|
||||
p->router_bound = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,11 +828,9 @@ struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, str
|
||||
|
||||
void tcp_proxy_client_destroy(struct tcp_proxy_client* p) {
|
||||
if (!p) return;
|
||||
int total = p->conn_count + p->socks_conn_count + p->http_conn_count;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "TCP proxy client destroying: lwip=%d socks=%d http=%d",
|
||||
p->conn_count, p->socks_conn_count, p->http_conn_count);
|
||||
if (p->inst) etcp_router_unbind(p->inst, ETCP_RT_ID_TCP_PROXY_CLIENT);
|
||||
if (p->inst && !p->inst->tcp_proxy_server.enabled) { udp_proxy_destroy(p->inst); icmp_proxy_destroy(p->inst); }
|
||||
if (p->router_bound) { etcp_router_unbind(p->inst, ETCP_RT_ID_TCP_PROXY_CLIENT); p->router_bound = 0; }
|
||||
|
||||
if (p->socks_listen) socks_proxy_close_listen(p->ua, p->socks_listen, NULL);
|
||||
socks_proxy_conn_free_all(&p->socks_conns, &p->socks_conn_count);
|
||||
|
||||
@@ -65,6 +65,7 @@ struct tcp_proxy_client_conn {
|
||||
|
||||
struct tcp_proxy_client {
|
||||
struct UTUN_INSTANCE* inst; // заимствован; NULL допустим для автономного TUN smoke test
|
||||
uint8_t router_bound; // собственный CLIENT binding установлен; rollback не снимает чужую регистрацию
|
||||
struct UASYNC* ua; // заимствованный event loop
|
||||
struct tun_if* tun; // собственный TUN или NULL для SOCKS/HTTP без TUN
|
||||
struct tcp_proxy_client_conn* conns; // список собственных lwIP-потоков
|
||||
@@ -78,13 +79,13 @@ struct tcp_proxy_client {
|
||||
int mapping_count; // число записей mappings, порты конфига в host byte order
|
||||
|
||||
// SOCKS proxy
|
||||
int socks_enabled; // запрошен SOCKS5; не гарантирует успешный listener
|
||||
int socks_enabled; // SOCKS5 listener обязателен при создании
|
||||
struct socks_proxy_conn* socks_conns; // собственные SOCKS5-клиенты
|
||||
int socks_conn_count; // число SOCKS5-клиентов
|
||||
struct listen_ctx* socks_listen; // собственный listener или NULL при отключении/ошибке
|
||||
|
||||
// HTTP forward proxy и CONNECT
|
||||
int http_proxy_enabled; // запрошен HTTP; не гарантирует успешный listener
|
||||
int http_proxy_enabled; // HTTP listener обязателен при создании
|
||||
struct socks_proxy_conn* http_conns; // собственные HTTP-клиенты
|
||||
int http_conn_count; // число HTTP-клиентов
|
||||
struct listen_ctx* http_listen; // собственный listener или NULL при отключении/ошибке
|
||||
@@ -94,7 +95,8 @@ struct tcp_proxy_client {
|
||||
// test_mode передаётся tun_init_nat: ненулевой использует тестовый TUN; mappings заимствуются до destroy.
|
||||
// SOCKS/HTTP создаются при enabled и непустом IPv4:port; via_node_id — общий exit.
|
||||
// Результат: собственный p или NULL при критической ошибке/отсутствии режима.
|
||||
// Ошибки listener/router bind/UDP/ICMP не делают create атомарным: проверять listener и диагностику отдельно.
|
||||
// Все выбранные входы и CLIENT binding обязательны; отказ полностью освобождает новые ресурсы.
|
||||
// Общие UDP/ICMP создаёт и уничтожает instance отдельно; create их не затрагивает.
|
||||
struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, struct UASYNC* ua,
|
||||
const char* tun_name, const char* tun_ip, int mtu, int test_mode,
|
||||
struct tcp_proxy_client_mapping_config* mappings, int mapping_count,
|
||||
@@ -102,7 +104,7 @@ struct tcp_proxy_client* tcp_proxy_client_create(struct UTUN_INSTANCE* inst, str
|
||||
int socks_enabled, const char* socks_addr,
|
||||
int http_proxy_enabled, const char* http_proxy_addr);
|
||||
// Остановить listeners, освободить потоки/TUN/lwIP и снять router binding; NULL допустим.
|
||||
// UDP/ICMP сохраняются, пока включён сервер того же inst. Не обнуляет inst->tcp_proxy_client.
|
||||
// Не затрагивает общие UDP/ICMP и не обнуляет inst->tcp_proxy_client.
|
||||
void tcp_proxy_client_destroy(struct tcp_proxy_client* p);
|
||||
// Router callback: conn->instance задаёт владельца, entry содержит метаданные router и передаёт владение.
|
||||
// Освобождает entry/dgram при любом исходе; CLOSE_ALL = пустой payload router, а не TCP-подкоманда.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// tcp_proxy_server.c — TCP прокси-сервер (exit node)
|
||||
#include "tcp_proxy_server.h"
|
||||
#include "udp_proxy.h"
|
||||
#include "icmp_proxy.h"
|
||||
#include "etcp.h"
|
||||
#include "etcp_api.h"
|
||||
#include "etcp_router.h"
|
||||
@@ -494,7 +492,8 @@ void tcp_proxy_server_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
if (subcmd == TCP_PROXY_SUBCMD_FIN) { tcp_proxy_server_handle_fin(inst, peer, stream_id); queue_dgram_free(entry); queue_entry_free(entry); return; }
|
||||
}
|
||||
}
|
||||
if (subcmd == TCP_PROXY_SUBCMD_DATA || subcmd == TCP_PROXY_SUBCMD_CLOSE || subcmd == TCP_PROXY_SUBCMD_FIN || subcmd == TCP_PROXY_SUBCMD_ERROR) {
|
||||
if (subcmd == TCP_PROXY_SUBCMD_DATA || subcmd == TCP_PROXY_SUBCMD_CLOSE || subcmd == TCP_PROXY_SUBCMD_FIN ||
|
||||
subcmd == TCP_PROXY_SUBCMD_ERROR || subcmd == TCP_PROXY_SUBCMD_WINDOW) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_PROXY, "PROXY subcmd=%02x sid=%08x — server conn not found, silent drop", subcmd, stream_id);
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return;
|
||||
}
|
||||
@@ -507,16 +506,18 @@ void tcp_proxy_server_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
// ====================================================================
|
||||
|
||||
int tcp_proxy_server_init(struct UTUN_INSTANCE* inst) {
|
||||
if (!inst) return -1;
|
||||
if (!inst) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy server: init requires instance"); return -1; }
|
||||
struct tcp_proxy_server* ctx = &inst->tcp_proxy_server;
|
||||
if (ctx->inst || ctx->conns) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy server: duplicate initialization"); return -1; }
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
if (!inst->config) return 0;
|
||||
ctx->enabled = inst->config->global.tcp_proxy_server_enabled;
|
||||
ctx->inst = inst;
|
||||
if (!ctx->enabled) return 0;
|
||||
etcp_router_bind(inst, ETCP_RT_ID_TCP_PROXY_SERVER, tcp_proxy_server_recv_cb);
|
||||
udp_proxy_init(inst, inst->ua);
|
||||
icmp_proxy_init(inst, inst->ua);
|
||||
if (!inst->config->global.tcp_proxy_server_enabled) return 0;
|
||||
if (inst->router_bindings.callbacks[ETCP_RT_ID_TCP_PROXY_SERVER] ||
|
||||
etcp_router_bind(inst, ETCP_RT_ID_TCP_PROXY_SERVER, tcp_proxy_server_recv_cb) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy server: service binding unavailable"); ctx->inst = NULL; return -1;
|
||||
}
|
||||
ctx->enabled = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "TCP proxy server initialized node=%016llx", (unsigned long long)inst->node_id);
|
||||
return 0;
|
||||
}
|
||||
@@ -524,12 +525,12 @@ int tcp_proxy_server_init(struct UTUN_INSTANCE* inst) {
|
||||
void tcp_proxy_server_destroy(struct UTUN_INSTANCE* inst) {
|
||||
if (!inst) return;
|
||||
struct tcp_proxy_server* ctx = &inst->tcp_proxy_server;
|
||||
if (!ctx->inst) return;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "TCP proxy server destroying: conn_count=%d", ctx->conn_count);
|
||||
struct tcp_proxy_server_conn* rc = ctx->conns;
|
||||
while (rc) { struct tcp_proxy_server_conn* next = rc->next; tcp_proxy_server_conn_free(rc); rc = next; }
|
||||
ctx->conns = NULL; ctx->enabled = 0;
|
||||
etcp_router_unbind(inst, ETCP_RT_ID_TCP_PROXY_SERVER);
|
||||
udp_proxy_destroy(inst);
|
||||
icmp_proxy_destroy(inst);
|
||||
ctx->conns = NULL;
|
||||
if (ctx->enabled) etcp_router_unbind(inst, ETCP_RT_ID_TCP_PROXY_SERVER);
|
||||
ctx->enabled = 0; ctx->inst = NULL;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "TCP proxy server destroyed");
|
||||
}
|
||||
Reference in new issue
Block a user