|
|
|
|
@ -49,6 +49,7 @@ static int tcp_proxy_client_send_data(struct tcp_proxy_client_conn* pc, const
|
|
|
|
|
static void tcp_proxy_client_tx_queue_drain_cb(struct ll_queue* q, void* arg); |
|
|
|
|
static void tcp_proxy_client_pause_resume_cb(struct ll_queue* q, void* arg); |
|
|
|
|
static void tcp_proxy_client_retry_timer_cb(void* arg); |
|
|
|
|
static void tcp_proxy_client_diag_timer_cb(void* arg); |
|
|
|
|
|
|
|
|
|
// ====================================================================
|
|
|
|
|
// Помощник ll_entry
|
|
|
|
|
@ -191,13 +192,25 @@ static void tcp_proxy_client_feed_from_transport(struct tcp_proxy_client_conn *p
|
|
|
|
|
uint32_t q_pre = queue_entry_count(pc->to_lwip); |
|
|
|
|
while (1) { |
|
|
|
|
uint16_t space = tcp_sndbuf(pc->pcb); |
|
|
|
|
if (space < TCP_MSS / 2) break; |
|
|
|
|
if (space < TCP_MSS / 2) { |
|
|
|
|
if (queue_entry_count(pc->to_lwip) > 0) |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, |
|
|
|
|
"PROXY FEED stalled sid=%08x snd_buf=%u to_lwip=%d snd_wnd=%u cwnd=%u", |
|
|
|
|
pc->stream_id, space, queue_entry_count(pc->to_lwip), |
|
|
|
|
pc->pcb->snd_wnd, pc->pcb->cwnd); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
struct ll_entry *e = queue_data_get(pc->to_lwip); |
|
|
|
|
if (!e) break; |
|
|
|
|
if (e->len <= space) { |
|
|
|
|
err_t ret = tcp_write(pc->pcb, e->dgram, e->len, TCP_WRITE_FLAG_COPY); |
|
|
|
|
if (ret == LERR_OK) { sent_any = 1; queue_dgram_free(e); queue_entry_free(e); } |
|
|
|
|
else { queue_data_put_first(pc->to_lwip, e); break; } |
|
|
|
|
else { |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, |
|
|
|
|
"PROXY FEED write fail sid=%08x len=%u ret=%d snd_buf=%u q=%d", |
|
|
|
|
pc->stream_id, e->len, ret, space, queue_entry_count(pc->to_lwip) + 1); |
|
|
|
|
queue_data_put_first(pc->to_lwip, e); break; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
queue_data_put_first(pc->to_lwip, e); |
|
|
|
|
break; |
|
|
|
|
@ -258,6 +271,7 @@ static err_t tcp_proxy_client_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t
|
|
|
|
|
if (tcp_proxy_client_send_connect(pc) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "TCP proxy client: send_connect failed sid=%08x to %d.%d.%d.%d:%d", pc->stream_id, pc->dest_ip[0], pc->dest_ip[1], pc->dest_ip[2], pc->dest_ip[3], ntohs(pc->dest_port)); tcp_arg(newpcb, NULL); tcp_abort(newpcb); queue_free(pc->to_lwip); u_free(pc); return LERR_MEM; } |
|
|
|
|
|
|
|
|
|
pc->next = p->conns; p->conns = pc; p->conn_count++; |
|
|
|
|
pc->diag_timer = uasync_set_timeout(p->ua, 5000, pc, tcp_proxy_client_diag_timer_cb, "tpc_diag"); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_PROXY, "TCP proxy client: new conn sid=%08x local_port=%u -> %d.%d.%d.%d:%d total_conns=%d snd_wnd=%u mss=%u", |
|
|
|
|
pc->stream_id, newpcb->local_port, pc->dest_ip[0], pc->dest_ip[1], pc->dest_ip[2], pc->dest_ip[3], ntohs(pc->dest_port), p->conn_count, newpcb->snd_wnd, newpcb->mss); |
|
|
|
|
return LERR_OK; |
|
|
|
|
@ -344,6 +358,28 @@ static void tcp_proxy_client_retry_timer_cb(void* arg) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void tcp_proxy_client_diag_timer_cb(void* arg) { |
|
|
|
|
struct tcp_proxy_client_conn* pc = (struct tcp_proxy_client_conn*)arg; |
|
|
|
|
if (!pc || !pc->proxy) return; |
|
|
|
|
pc->diag_timer = NULL; |
|
|
|
|
if (pc->rem_closed) return; |
|
|
|
|
struct tcp_pcb* pcb = pc->pcb; |
|
|
|
|
if (!pcb || pcb->state == CLOSED) return; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, |
|
|
|
|
"PROXY DIAG sid=%08x st=%s fin_l=%d fin_r=%d " |
|
|
|
|
"rcv_wnd=%u rcv_ann=%u snd_wnd=%u snd_buf=%u cwnd=%u " |
|
|
|
|
"unsent=%d unacked=%d ooseq=%d " |
|
|
|
|
"tx_q=%d to_lwip=%d to_exit=%u from_exit=%u bp=%u err=%d rem_closed=%d", |
|
|
|
|
pc->stream_id, tcp_debug_state_str(pcb->state), |
|
|
|
|
pc->fin_local, pc->fin_remote, |
|
|
|
|
pcb->rcv_wnd, pcb->rcv_ann_wnd, pcb->snd_wnd, (unsigned)tcp_sndbuf(pcb), pcb->cwnd, |
|
|
|
|
tcp_seg_count(pcb->unsent), tcp_seg_count(pcb->unacked), tcp_seg_count(pcb->ooseq), |
|
|
|
|
pc->tx_queue ? queue_entry_count(pc->tx_queue) : -1, |
|
|
|
|
pc->to_lwip ? queue_entry_count(pc->to_lwip) : -1, |
|
|
|
|
pc->bytes_to_exit, pc->bytes_from_exit, pc->bp_count, pc->error, pc->rem_closed); |
|
|
|
|
pc->diag_timer = uasync_set_timeout(pc->proxy->ua, 5000, pc, tcp_proxy_client_diag_timer_cb, "tpc_diag"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static err_t tcp_proxy_client_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { |
|
|
|
|
struct tcp_proxy_client_conn *pc = (struct tcp_proxy_client_conn *)arg; |
|
|
|
|
if (!pc || !pc->proxy || pc->rem_closed) { if (p) pbuf_free(p); return LERR_OK; } |
|
|
|
|
@ -513,6 +549,7 @@ static void tcp_proxy_client_conn_free(struct tcp_proxy_client_conn *pc) {
|
|
|
|
|
queue_free(pc->tx_queue); pc->tx_queue = NULL; |
|
|
|
|
} |
|
|
|
|
if (pc->tx_retry_timer) { uasync_cancel_timeout(p->ua, pc->tx_retry_timer); pc->tx_retry_timer = NULL; } |
|
|
|
|
if (pc->diag_timer) { uasync_cancel_timeout(p->ua, pc->diag_timer); pc->diag_timer = NULL; } |
|
|
|
|
if (p && p->inst) etcp_router_cancel_send_ready(p->inst, TOPO_GROUP_UTUN, p->via_node_id, ETCP_RT_ID_TCP_PROXY_SERVER, &pc->tx_waiter); |
|
|
|
|
u_free(pc); |
|
|
|
|
} |
|
|
|
|
@ -794,6 +831,7 @@ void tcp_proxy_client_destroy(struct tcp_proxy_client* p) {
|
|
|
|
|
queue_free(pc->tx_queue); pc->tx_queue = NULL; |
|
|
|
|
} |
|
|
|
|
if (pc->tx_retry_timer) { uasync_cancel_timeout(p->ua, pc->tx_retry_timer); pc->tx_retry_timer = NULL; } |
|
|
|
|
if (pc->diag_timer) { uasync_cancel_timeout(p->ua, pc->diag_timer); pc->diag_timer = NULL; } |
|
|
|
|
if (p->inst) etcp_router_cancel_send_ready(p->inst, TOPO_GROUP_UTUN, p->via_node_id, ETCP_RT_ID_TCP_PROXY_SERVER, &pc->tx_waiter); |
|
|
|
|
u_free(pc); pc = next; |
|
|
|
|
} |
|
|
|
|
|