fix tcp_proxy connection lifecycle: closing_sent, destroy transport, shutdown+timer on exit
- Add closing_sent flag to proxy_conn (CLOSE sent to exit, no need to wait for reply) - proxy_poll_cb: send CLOSE when done || sndbuf==0; cleanup when tun && (rem||sent) - Destroy transport in proxy_poll_cb cleanup (fix 56-byte leak) - remote_proxy_handle_close: shutdown(SHUT_WR) + 2s timer instead of immediate rp_conn_free - Remove SHUTDOWN subcommand entirely (not needed with new lifecycle)
This commit is contained in:
1 parent
ca3215ab91
commit
ba03cab182
3 files changed
+28
-9
No files matched your search
+11
-1
@@ -225,6 +225,13 @@ int remote_proxy_handle_data(struct UTUN_INSTANCE* inst, struct ll_entry* entry,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rp_close_timer_cb(void* arg) {
|
||||
struct remote_proxy_conn* rc = (struct remote_proxy_conn*)arg;
|
||||
if (!rc || rc->connected == -1) return;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "RP CLOSE timer stream=%016llx", (unsigned long long)rc->stream_id);
|
||||
rp_conn_free(rc);
|
||||
}
|
||||
|
||||
void remote_proxy_handle_close(struct UTUN_INSTANCE* inst, uint64_t stream_id) {
|
||||
if (!inst) return;
|
||||
struct remote_proxy_ctx* ctx = &inst->remote_proxy;
|
||||
@@ -233,8 +240,11 @@ void remote_proxy_handle_close(struct UTUN_INSTANCE* inst, uint64_t stream_id) {
|
||||
struct remote_proxy_conn* rc = *prev;
|
||||
if (rc->stream_id == stream_id) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "RP CLOSE stream=%016llx", (unsigned long long)stream_id);
|
||||
*prev = rc->next;
|
||||
if (rc->sock != SOCKET_INVALID && rc->connected == 1) shutdown(rc->sock, SHUT_WR);
|
||||
*prev = rc->next; rp_conn_free(rc); return;
|
||||
if (rc->read_id) { uasync_remove_socket_t(rc->ua, rc->sock); rc->read_id = NULL; }
|
||||
uasync_set_timeout(rc->ua, 20000, rc, rp_close_timer_cb, "rp_close");
|
||||
return;
|
||||
}
|
||||
prev = &rc->next;
|
||||
}
|
||||
|
||||
+16
-8
@@ -309,18 +309,25 @@ static void proxy_err_cb(void *arg, err_t err) {
|
||||
static err_t proxy_poll_cb(void *arg, struct tcp_pcb *pcb) {
|
||||
struct proxy_conn *pc = (struct proxy_conn *)arg;
|
||||
if (!pc) return LERR_OK;
|
||||
if (pc->closing_tun && !pc->closing_rem && pc->transport && pc->transport_to_uip
|
||||
&& queue_entry_count(pc->transport_to_uip) == 0) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLOSE stream=%016llx tun=1 (no pending)", (unsigned long long)pc->remote_stream_id);
|
||||
pc->transport->ops->close(pc->transport);
|
||||
if (pc->closing_tun && !pc->closing_sent && !pc->closing_rem && pc->transport && pc->pcb) {
|
||||
uint32_t pending = pc->transport_to_uip ? queue_entry_count(pc->transport_to_uip) : 0;
|
||||
int done = (pending == 0 && pc->pcb->unsent == NULL && pc->pcb->unacked == NULL);
|
||||
uint32_t sndbuf = tcp_sndbuf(pc->pcb);
|
||||
if (done || sndbuf == 0) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLOSE stream=%016llx tun=1 pending=%u done=%d sndbuf=%u",
|
||||
(unsigned long long)pc->remote_stream_id, pending, done, sndbuf);
|
||||
pc->transport->ops->close(pc->transport);
|
||||
}
|
||||
}
|
||||
if (pc->closing_tun && pc->closing_rem && pc->pcb) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLOSE stream=%016llx tun=1 rem=1", (unsigned long long)pc->remote_stream_id);
|
||||
if (pc->closing_tun && (pc->closing_rem || pc->closing_sent) && pc->pcb) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLEANUP stream=%016llx tun=1 rem=%d sent=%d",
|
||||
(unsigned long long)pc->remote_stream_id, pc->closing_rem, pc->closing_sent);
|
||||
struct tcp_pcb *save = pc->pcb;
|
||||
tcp_arg(save, NULL); pc->pcb = NULL; tcp_close(save);
|
||||
struct tcp_proxy *proxy = pc->proxy;
|
||||
struct proxy_conn **prev = &proxy->conns;
|
||||
while (*prev) { if (*prev == pc) { *prev = pc->next; proxy->conn_count--; break; } prev = &(*prev)->next; }
|
||||
if (pc->transport) { pc->transport->ops->destroy(pc->transport); pc->transport = NULL; }
|
||||
if (pc->eim_mapping) { pc->eim_mapping->delete_at_tb = get_time_tb() + proxy->eim_timeout_tb; pc->eim_mapping = NULL; }
|
||||
if (pc->uip_to_transport) { struct ll_entry *e2; while ((e2 = queue_data_get(pc->uip_to_transport))) { queue_dgram_free(e2); queue_entry_free(e2); } queue_free(pc->uip_to_transport); }
|
||||
if (pc->transport_to_uip) { struct ll_entry *e2; while ((e2 = queue_data_get(pc->transport_to_uip))) { queue_dgram_free(e2); queue_entry_free(e2); } queue_free(pc->transport_to_uip); }
|
||||
@@ -602,8 +609,8 @@ static void etcp_transport_close(struct tcp_proxy_transport* t) {
|
||||
etcp_route_send(et->inst, et->remote_node_id, e); } else queue_entry_free(e);
|
||||
}
|
||||
et->connected = 0;
|
||||
if (et->conn) { et->conn->transport = NULL; et->conn->closing_rem = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY REM=1 stream=%016llx (transport close)", (unsigned long long)et->conn->remote_stream_id);
|
||||
if (et->conn) { et->conn->transport = NULL; et->conn->closing_sent = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY SENT=1 stream=%016llx (transport close)", (unsigned long long)et->conn->remote_stream_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,6 +698,7 @@ void tcp_proxy_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CONNECT) {
|
||||
uint64_t src_node_id = conn ? conn->peer_node_id : (inst ? inst->node_id : 0);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "RP CONNECT recv stream=%016llx", (unsigned long long)stream_id);
|
||||
remote_proxy_handle_connect(inst, entry, stream_id, src_node_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ struct proxy_conn {
|
||||
uint16_t dest_port;
|
||||
int closing_tun; // 1 = TUN/lwIP side sent FIN (waiting for remote)
|
||||
int closing_rem; // 1 = remote/transport closed (waiting for TUN)
|
||||
int closing_sent; // 1 = CLOSE sent to exit via transport->close()
|
||||
int active; // 1 = outgoing connection
|
||||
struct tcp_proxy_mapping* eim_mapping;
|
||||
uint64_t remote_stream_id; // stream ID for remote proxy (0=local)
|
||||
|
||||
Reference in new issue
Block a user