From 238fb0eb2390f2426ff466d3ad54497a44ff5a52 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 13 May 2026 02:32:26 +0300 Subject: [PATCH] fix remote_proxy: cleanup socket on EOF/error/connect-fail to prevent infinite callback loop --- src/remote_proxy.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/remote_proxy.c b/src/remote_proxy.c index 34b3bd50..c7e4f042 100644 --- a/src/remote_proxy.c +++ b/src/remote_proxy.c @@ -30,6 +30,7 @@ static struct remote_proxy_ctx* g_rp_ctx = NULL; static void rp_sock_read_cb (socket_t sock, void* arg); static void rp_sock_write_cb(socket_t sock, void* arg); static void rp_sock_error_cb(socket_t sock, void* arg); +static void rp_conn_free(struct remote_proxy_conn* rc); static int rp_send_msg(struct UTUN_INSTANCE* inst, uint64_t dst, uint8_t subcmd, uint64_t sid, const uint8_t* data, size_t len) { @@ -62,13 +63,13 @@ static void rp_sock_read_cb(socket_t sock, void* arg) { if (n > 0) { struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_DATA, rc->stream_id, buf, (size_t)n); - } else if (n == 0) { - DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "remote_proxy: EOF stream=%016llx", (unsigned long long)rc->stream_id); + } else { + if (n == 0) DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "remote_proxy: EOF stream=%016llx", (unsigned long long)rc->stream_id); + else DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: recv error %s", strerror(errno)); struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, NULL, 0); rc->connected = -1; - } else if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { - DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: recv error %s", strerror(errno)); + rp_conn_free(rc); } } @@ -93,21 +94,30 @@ static void rp_sock_write_cb(socket_t sock, void* arg) { struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; if (inst) rp_send_connected(inst, rc->peer_node_id, rc->stream_id, 0, TCP_PROXY_CONNECTED_REFUSED); rc->connected = -1; + rp_conn_free(rc); } } } static void rp_sock_error_cb(socket_t sock, void* arg) { (void)sock; struct remote_proxy_conn* rc = (struct remote_proxy_conn*)arg; - DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: socket error stream=%016llx", (unsigned long long)rc->stream_id); - if (rc) rc->connected = -1; + if (!rc || rc->sock == SOCKET_INVALID) return; + DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "remote_proxy: socket error stream=%016llx", (unsigned long long)(rc ? rc->stream_id : 0)); + rc->connected = -1; + struct UTUN_INSTANCE* inst = rc->ctx ? rc->ctx->inst : NULL; + if (inst) rp_send_msg(inst, rc->peer_node_id, TCP_PROXY_SUBCMD_CLOSE, rc->stream_id, NULL, 0); + rp_conn_free(rc); } static void rp_conn_free(struct remote_proxy_conn* rc) { if (!rc) return; + if (rc->ctx) { + struct remote_proxy_conn** prev = &rc->ctx->conns; + while (*prev) { if (*prev == rc) { *prev = rc->next; break; } prev = &(*prev)->next; } + } if (rc->sock != SOCKET_INVALID) { if (rc->read_id) { uasync_remove_socket_t(rc->ua, rc->sock); rc->read_id = NULL; } - socket_close_wrapper(rc->sock); + socket_close_wrapper(rc->sock); rc->sock = SOCKET_INVALID; } u_free(rc); }