redesign TCP close: closing_tun/closing_rem flags, poll-driven cleanup, proper half-close
This commit is contained in:
1 parent
238fb0eb23
commit
cec736a4b0
3 files changed
+26
-33
No files matched your search
+23
-30
@@ -211,7 +211,7 @@ static err_t proxy_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) {
|
||||
|
||||
struct proxy_conn *pc = u_calloc(1, sizeof(struct proxy_conn));
|
||||
if (!pc) return LERR_MEM;
|
||||
pc->proxy = p; pc->pcb = newpcb; pc->closing = 0; pc->half_closed = 0;
|
||||
pc->proxy = p; pc->pcb = newpcb; pc->closing_tun = 0; pc->closing_rem = 0;
|
||||
|
||||
struct tcp_proxy_mapping *m = find_mapping_by_port(p, newpcb->local_port);
|
||||
if (m) { memcpy(pc->dest_ip, m->remote_ip, 4); pc->dest_port = m->remote_port; }
|
||||
@@ -250,22 +250,9 @@ static err_t proxy_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t
|
||||
if (!pc) { if (p) pbuf_free(p); return LERR_OK; }
|
||||
|
||||
if (p == NULL || err != LERR_OK) {
|
||||
struct tcp_proxy *proxy = pc->proxy;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "TCP proxy: remote closed (FIN/EOF), stream=%s active=%d",
|
||||
DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "TCP proxy: TUN FIN received, stream=%s active=%d",
|
||||
pc->active ? "active" : "passive", pc->active);
|
||||
pc->closing = 1;
|
||||
if (pc->transport) { pc->transport->ops->destroy(pc->transport); pc->transport = NULL; }
|
||||
struct tcp_pcb *pcb = pc->pcb;
|
||||
if (pcb) { tcp_arg(pcb, NULL); pc->pcb = NULL; tcp_close(pcb); }
|
||||
struct proxy_conn **prev = &proxy->conns;
|
||||
while (*prev) {
|
||||
if (*prev == pc) { *prev = pc->next; proxy->conn_count--; break; }
|
||||
prev = &(*prev)->next;
|
||||
}
|
||||
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); }
|
||||
u_free(pc);
|
||||
pc->closing_tun = 1;
|
||||
return LERR_OK;
|
||||
}
|
||||
|
||||
@@ -275,7 +262,7 @@ static err_t proxy_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t
|
||||
if (e) queue_data_put(pc->uip_to_transport, e);
|
||||
tcp_recved(pcb, p->tot_len);
|
||||
pbuf_free(p);
|
||||
} else if (pc->transport && !pc->half_closed) {
|
||||
} else if (pc->transport && !pc->closing_rem) {
|
||||
uint16_t len = p->tot_len;
|
||||
uint8_t *data = u_malloc(len);
|
||||
if (data) {
|
||||
@@ -305,7 +292,7 @@ static void proxy_err_cb(void *arg, err_t err) {
|
||||
struct proxy_conn *pc = (struct proxy_conn *)arg;
|
||||
if (!pc) return;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP proxy: tcp error %d", err);
|
||||
pc->closing = 1;
|
||||
pc->closing_tun = 1;
|
||||
if (pc->transport) pc->transport->ops->close(pc->transport);
|
||||
}
|
||||
|
||||
@@ -313,8 +300,16 @@ 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;
|
||||
proxy_feed_from_transport(pc);
|
||||
if (pc->closing && pc->transport == NULL && pc->pcb) {
|
||||
tcp_arg(pc->pcb, NULL); pc->pcb = NULL; tcp_close(pcb);
|
||||
if (pc->closing_tun && pc->closing_rem && pc->pcb) {
|
||||
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->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); }
|
||||
u_free(pc);
|
||||
}
|
||||
return LERR_OK;
|
||||
}
|
||||
@@ -324,7 +319,7 @@ static err_t proxy_connected_cb(void *arg, struct tcp_pcb *pcb, err_t err) {
|
||||
if (!pc) return LERR_ABRT;
|
||||
if (err != LERR_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP proxy: active connect failed: %d", err);
|
||||
pc->closing = 1;
|
||||
pc->closing_tun = 1;
|
||||
return LERR_ABRT;
|
||||
}
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TRAFFIC, "TCP proxy: active connect established to %d.%d.%d.%d:%d cwnd=%u snd_wnd=%u snd_buf=%u",
|
||||
@@ -486,7 +481,7 @@ static void sock_transport_close(struct tcp_proxy_transport* t) {
|
||||
if(st->read_id) { uasync_remove_socket_t(st->ua, st->sock); st->read_id = NULL; }
|
||||
if(st->write_id) { uasync_remove_socket_t(st->ua, st->sock); st->write_id = NULL; }
|
||||
socket_close_wrapper(st->sock); st->sock = SOCKET_INVALID; st->connected = 0;
|
||||
if(pc && !pc->closing) pc->closing = 1;
|
||||
if(pc && !pc->closing_rem) pc->closing_rem = 1;
|
||||
if(pc) pc->transport = NULL;
|
||||
}
|
||||
|
||||
@@ -591,7 +586,7 @@ 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;
|
||||
if (et->conn) { et->conn->transport = NULL; et->conn->closing_rem = 1; }
|
||||
}
|
||||
|
||||
static void etcp_transport_destroy(struct tcp_proxy_transport* t) {
|
||||
@@ -654,7 +649,7 @@ static void handle_connected(struct tcp_proxy* p, uint64_t stream_id, struct ll_
|
||||
}
|
||||
}
|
||||
else { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP proxy: remote refused stream=%016llx", (unsigned long long)stream_id);
|
||||
pc->closing = 1; }
|
||||
pc->closing_rem = 1; }
|
||||
}
|
||||
queue_entry_free(entry); queue_dgram_free(entry);
|
||||
}
|
||||
@@ -699,10 +694,8 @@ void tcp_proxy_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
if (subcmd == TCP_PROXY_SUBCMD_CLOSE) {
|
||||
struct proxy_conn* pc = find_pc_by_stream(proxy, stream_id);
|
||||
if (pc) {
|
||||
pc->closing = 1;
|
||||
pc->closing_rem = 1;
|
||||
if (pc->transport) { pc->transport->ops->destroy(pc->transport); pc->transport = NULL; }
|
||||
struct tcp_pcb *pcb = pc->pcb;
|
||||
if (pcb) { tcp_arg(pcb, NULL); pc->pcb = NULL; tcp_close(pcb); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -817,7 +810,7 @@ struct proxy_conn* tcp_proxy_active_open(struct tcp_proxy* p, const char* dest_i
|
||||
|
||||
struct proxy_conn* pc = u_calloc(1, sizeof(struct proxy_conn));
|
||||
if (!pc) return NULL;
|
||||
pc->proxy = p; pc->active = 1; pc->closing = 0; pc->half_closed = 0;
|
||||
pc->proxy = p; pc->active = 1; pc->closing_tun = 0; pc->closing_rem = 0;
|
||||
pc->dest_port = htons(dest_port);
|
||||
pc->dest_ip[0] = (uint8_t)a0; pc->dest_ip[1] = (uint8_t)a1; pc->dest_ip[2] = (uint8_t)a2; pc->dest_ip[3] = (uint8_t)a3;
|
||||
pc->tun_ip = htonl((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
|
||||
@@ -869,7 +862,7 @@ ssize_t tcp_proxy_active_recv(struct tcp_proxy* p, struct proxy_conn* pc, uint8_
|
||||
int tcp_proxy_active_close(struct tcp_proxy* p, struct proxy_conn* pc) {
|
||||
(void)p;
|
||||
if (!pc || !pc->active) return -1;
|
||||
pc->closing = 1;
|
||||
pc->closing_tun = 1;
|
||||
tcp_close(pc->pcb);
|
||||
return 0;
|
||||
}
|
||||
@@ -877,7 +870,7 @@ int tcp_proxy_active_close(struct tcp_proxy* p, struct proxy_conn* pc) {
|
||||
int tcp_proxy_active_send_done(struct tcp_proxy* p, struct proxy_conn* pc) {
|
||||
(void)p;
|
||||
if (!pc || !pc->active || !pc->pcb) return 1;
|
||||
if (pc->closing) return 1;
|
||||
if (pc->closing_tun) return 1;
|
||||
int q = queue_entry_count(pc->transport_to_uip);
|
||||
if (q > 0) return 0;
|
||||
if (pc->pcb->unsent || pc->pcb->unacked) return 0;
|
||||
|
||||
+2
-2
@@ -57,8 +57,8 @@ struct proxy_conn {
|
||||
uint8_t dest_ip[4]; // proxy target IP (where to forward OS socket)
|
||||
uint32_t tun_ip; // TUN IP (what client connected to, for uip_hostaddr)
|
||||
uint16_t dest_port;
|
||||
int closing;
|
||||
int half_closed;
|
||||
int closing_tun; // 1 = TUN/lwIP side sent FIN (waiting for remote)
|
||||
int closing_rem; // 1 = remote/transport closed (waiting for TUN)
|
||||
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